G:/ScriptBasic/source/commands/time.c

Go to the documentation of this file.
00001 /* time.c
00002 */
00003 #include <time.h>
00004 #include <stdlib.h>
00005 #include <stdio.h>
00006 #include <string.h>
00007 
00008 #include "../command.h"
00009 
00010 /*--------------------------------------------------------------------------------------------
00011 
00012  This file implements the time and date handling ScriptBasic functions. Before
00013  strating the real COMMANDs we have to implement a few standard functions. These are
00014  mktime and gmtime. Why should we reinvent the wheel?
00015 
00016  For two reasons: mktime converts GMT time to local time. We do not need this conversion.
00017  mktime adjust the year value in case month value is out of range (less than zero or larger
00018  than eleven). It is implemented this way on Windows NT, but man pages do not say anything
00019  about this feature. To be sure, I copied and a bit modified to our needs the code here.
00020  Just to be sure that it works on all system the same way.
00021 
00022  The problem with the function gmtime is more serious. NEVER USE POSIX gmtime() !!!!!!
00023 
00024  The reason: I am paranoid. The POSIX definition of the function is that it has to
00025  return a pointer to a structure containing the values. But where does the structure
00026  come from? Is it static or is it allocated? If this is static, then it is not thread
00027  safe. If this is allocated, who will release the memory.
00028 
00029  Instead here is a modified version that requests the caller to pass a pointer to an allocated and
00030  available struct tm buffer, and the returned pointer will point to this buffer.
00031 
00032  --------------------------------------------------------------------------------------------*/
00033 
00034 #define _DAY_SEC           (24L * 60L * 60L)    /* secs in a day */
00035 #define _YEAR_SEC          (365L * _DAY_SEC)    /* secs in a year */
00036 #define _FOUR_YEAR_SEC     (1461L * _DAY_SEC)   /* secs in a 4 year interval */
00037 #define _BASE_DOW          4                    /* 01-01-70 was a Thursday */
00038 #define _BASE_YEAR         70L                  /* 1970 is the base year */
00039 #define _MAX_YEAR          138L                 /* 2038 is the max year */
00040 #define _LEAP_YEAR_ADJUST  17L                  /* Leap years 1900 - 1970 */
00041 static int _lpdays[] = { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
00042 static int _days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
00043 /*
00044  * ChkAdd evaluates to TRUE if dest = src1 + src2 has overflowed
00045  */
00046 #define ChkAdd(dest, src1, src2)   ( ((src1 >= 0L) && (src2 >= 0L) \
00047     && (dest < 0L)) || ((src1 < 0L) && (src2 < 0L) && (dest >= 0L)) )
00048 
00049 /*
00050  * ChkMul evaluates to TRUE if dest = src1 * src2 has overflowed
00051  */
00052 #define ChkMul(dest, src1, src2)   ( src1 ? (dest/src1 != src2) : 0 )
00053 
00054 static struct tm * mygmtime (time_t *timp, struct tm *ptb);
00055 
00056 static long mygmktime(struct tm *tb){
00057   time_t tmptm1, tmptm2, tmptm3;
00058   struct tm *tbtemp,Qtbtemp;
00059 
00060   /*
00061   * First, make sure tm_year is reasonably close to being in range.
00062   */
00063   if( ((tmptm1 = tb->tm_year) < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR+ 1) )
00064      goto err_mktime;
00065 
00066   /*
00067   * Adjust month value so it is in the range 0 - 11.  This is because
00068   * we don't know how many days are in months 12, 13, 14, etc.
00069   */
00070   if( (tb->tm_mon < 0) || (tb->tm_mon > 11) ) {
00071 
00072   /* no danger of overflow because the range check above.  */
00073   tmptm1 += (tb->tm_mon / 12);
00074   if( (tb->tm_mon %= 12) < 0 ) {
00075     tb->tm_mon += 12;
00076     tmptm1--;
00077     }
00078 
00079   /*
00080   * Make sure year count is still in range.
00081   */
00082   if( (tmptm1 < _BASE_YEAR - 1) || (tmptm1 > _MAX_YEAR + 1) )
00083      goto err_mktime;
00084   }
00085 
00086   /***** HERE: tmptm1 holds number of elapsed years *****/
00087 
00088   /*
00089   * Calculate days elapsed minus one, in the given year, to the given
00090   * month. Check for leap year and adjust if necessary.
00091   */
00092   tmptm2 = _days[tb->tm_mon];
00093   if( !(tmptm1 & 3) && (tb->tm_mon > 1) )
00094     tmptm2++;
00095 
00096   /*
00097   * Calculate elapsed days since base date (midnight, 1/1/70, UTC)
00098   *
00099   * 365 days for each elapsed year since 1970, plus one more day for
00100   * each elapsed leap year. no danger of overflow because of the range
00101   * check (above) on tmptm1.
00102   */
00103   tmptm3 = (tmptm1 - _BASE_YEAR) * 365L + ((tmptm1 - 1L) >> 2)
00104           - _LEAP_YEAR_ADJUST;
00105 
00106   /* elapsed days to current month (still no possible overflow) */
00107   tmptm3 += tmptm2;
00108 
00109   /* elapsed days to current date. overflow is now possible. */
00110   tmptm1 = tmptm3 + (tmptm2 = (long)(tb->tm_mday));
00111   if( ChkAdd(tmptm1, tmptm3, tmptm2) ) goto err_mktime;
00112 
00113   /***** HERE: tmptm1 holds number of elapsed days *****/
00114 
00115   /* Calculate elapsed hours since base date */
00116   tmptm2 = tmptm1 * 24L;
00117   if( ChkMul(tmptm2, tmptm1, 24L) )goto err_mktime;
00118 
00119   tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_hour);
00120   if( ChkAdd(tmptm1, tmptm2, tmptm3) )goto err_mktime;
00121 
00122   /***** HERE: tmptm1 holds number of elapsed hours *****/
00123 
00124   /* Calculate elapsed minutes since base date */
00125 
00126   tmptm2 = tmptm1 * 60L;
00127   if( ChkMul(tmptm2, tmptm1, 60L) )goto err_mktime;
00128 
00129   tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_min);
00130   if ( ChkAdd(tmptm1, tmptm2, tmptm3) )goto err_mktime;
00131 
00132   /***** HERE: tmptm1 holds number of elapsed minutes *****/
00133 
00134   /* Calculate elapsed seconds since base date */
00135 
00136   tmptm2 = tmptm1 * 60L;
00137   if( ChkMul(tmptm2, tmptm1, 60L) )goto err_mktime;
00138 
00139   tmptm1 = tmptm2 + (tmptm3 = (long)tb->tm_sec);
00140   if ( ChkAdd(tmptm1, tmptm2, tmptm3) )goto err_mktime;
00141 
00142   /***** HERE: tmptm1 holds number of elapsed seconds *****/
00143   if( (tbtemp = mygmtime(&tmptm1,&Qtbtemp)) == NULL )goto err_mktime;
00144 
00145   *tb = *tbtemp;
00146   return tmptm1;
00147 
00148 err_mktime:
00149   /* All errors come to here */
00150   return -1L;
00151 }
00152 
00153 static struct tm * mygmtime (time_t *timp, struct tm *ptb){
00154   long caltim = *timp;            /* calendar time to convert */
00155   int islpyr = 0;                 /* is-current-year-a-leap-year flag */
00156   int tmptim;
00157   int *mdays;                /* pointer to days or lpdays */
00158 
00159   if( caltim < 0L )return NULL;
00160 
00161   /*
00162    * Determine years since 1970. First, identify the four-year interval
00163    * since this makes handling leap-years easy (note that 2000 IS a
00164    * leap year and 2100 is out-of-range).
00165    */
00166   tmptim = (int)(caltim / _FOUR_YEAR_SEC);
00167   caltim -= ((long)tmptim * _FOUR_YEAR_SEC);
00168 
00169   /*
00170    * Determine which year of the interval
00171    */
00172   tmptim = (tmptim * 4) + 70;         /* 1970, 1974, 1978,...,etc. */
00173 
00174   if( caltim >= _YEAR_SEC ) {
00175     tmptim++;                       /* 1971, 1975, 1979,...,etc. */
00176     caltim -= _YEAR_SEC;
00177 
00178     if( caltim >= _YEAR_SEC ) {
00179       tmptim++;                   /* 1972, 1976, 1980,...,etc. */
00180       caltim -= _YEAR_SEC;
00181 
00182       /*
00183       * Note, it takes 366 days-worth of seconds to get past a leap
00184       * year.
00185       */
00186       if( caltim >= (_YEAR_SEC + _DAY_SEC) ){
00187         tmptim++;           /* 1973, 1977, 1981,...,etc. */
00188         caltim -= (_YEAR_SEC + _DAY_SEC);
00189         }else {
00190         /*
00191         * In a leap year after all, set the flag.
00192         */
00193         islpyr++;
00194         }
00195       }
00196     }
00197 
00198   /*
00199   * tmptim now holds the value for tm_year. caltim now holds the
00200   * number of elapsed seconds since the beginning of that year.
00201   */
00202   ptb->tm_year = tmptim;
00203 
00204   /*
00205    * Determine days since January 1 (0 - 365). This is the tm_yday value.
00206    * Leave caltim with number of elapsed seconds in that day.
00207    */
00208   ptb->tm_yday = (int)(caltim / _DAY_SEC);
00209   caltim -= (long)(ptb->tm_yday) * _DAY_SEC;
00210 
00211   /*
00212   * Determine months since January (0 - 11) and day of month (1 - 31)
00213   */
00214   if( islpyr )mdays = _lpdays; else mdays = _days;
00215 
00216   for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
00217 
00218   ptb->tm_mon = --tmptim;
00219 
00220   ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
00221 
00222   /*
00223    * Determine days since Sunday (0 - 6)
00224    */
00225   ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7;
00226 
00227   /*
00228    *  Determine hours since midnight (0 - 23), minutes after the hour
00229    *  (0 - 59), and seconds after the minute (0 - 59).
00230    */
00231   ptb->tm_hour = (int)(caltim / 3600);
00232   caltim -= (long)ptb->tm_hour * 3600L;
00233 
00234   ptb->tm_min = (int)(caltim / 60);
00235   ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
00236 
00237   ptb->tm_isdst = 0;
00238   return( (struct tm *)ptb );
00239   }
00240 
00241 static long TimeDifference(void){
00242   time_t lTime;
00243   struct tm GmTime,*pGmTime;
00244 
00245 /* calculate the time zone difference and day light saving hour together */
00246 /* not too elegant, but works */
00247   lTime = (time_t)time(NULL);
00248   pGmTime = mygmtime(&lTime,&GmTime);
00249   pGmTime->tm_isdst = -1;
00250   return (long)(lTime - mktime(pGmTime));
00251   }
00252 
00253 #define MONTH_NAME_LEN 9
00254 static char *MonthName[] = {
00255   "January", "February", "March", "April", "May", "June", 
00256   "July", "August", "September", "October", "November", "December"
00257   };
00258 #define WEEK_DAY_NAME_LEN 9
00259 static char *WeekDayName[] ={
00260   "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
00261   };
00262 
00263 
00301 COMMAND(FORMATDATE)
00302 #if NOTIMP_FORMATDATE
00303 NOTIMPLEMENTED;
00304 #else
00305 
00306   VARIABLE vFormatString,vTimeValue;
00307   time_t lTimeValue;
00308   NODE nItem;
00309   char *pszFormatString;
00310   struct tm *pGmTime,GmTime;
00311   char *s,*r,
00312         szNumberBuffer[5]; /* four digits + terminating zero */
00313   int hour,len;
00314 
00315   /* this is an operator and not a command, therefore we do not have our own mortal list */
00316   USE_CALLER_MORTALS;
00317 
00318   nItem = PARAMETERLIST;
00319 
00320   vFormatString = CONVERT2STRING(_EVALUATEEXPRESSION(CAR(nItem)));
00321   ASSERTOKE;
00322   if( vFormatString == NULL )ERROR(COMMAND_ERROR_INVALID_TIME_FORMAT);
00323 
00324   CONVERT2ZCHAR(vFormatString,pszFormatString);
00325 
00326   nItem = CDR(nItem);
00327   if( nItem ){
00328     vTimeValue = EVALUATEEXPRESSION(CAR(nItem));
00329     ASSERTOKE;
00330     }else vTimeValue = NULL;
00331 
00332   if( vTimeValue )
00333     lTimeValue = LONGVALUE(CONVERT2LONG(vTimeValue));
00334   else
00335     lTimeValue = (long)time(NULL)+ TimeDifference();
00336 
00337   /*
00338      Note that MONTHNAME and WEEKDAYNAME are long enough to be longer than the
00339      longest month name or week-day name. In case the month and week-day names are
00340      changed they should not be longer than 12 characters.
00341      YEAR         four digit year
00342      YY           two digit year
00343      MON          three letter abbreviation of the month name
00344      MM           month
00345      0M           month with leading zero if needed
00346      *MONTH-NAME* name of the month
00347      DD           day of the month
00348      0D           day of the month with leading zero if needed
00349      WD           week day on a single digit starting with sunday=0
00350      WEEKDAY-NAME the name of the weekday
00351      WDN          three letter abbreviation fo the week day name
00352      HH           hours (24 hours notation)
00353      0H           hours with leading zero if needed (24 hours notation)
00354      hh           hours (12 hours notation)
00355      0h           hours with leading zero if needed (12 hours notation)
00356      mm           minutes
00357      0m           minutes with leading zero if needed
00358      am
00359      pm   is am or pm
00360   
00361   */
00362   pGmTime = mygmtime(&lTimeValue,&GmTime);
00363 
00364   s = pszFormatString;
00365   while( *s ){
00366 
00367     if( !memcmp(s,"WDN",3) ){
00368       len = strlen(r = WeekDayName[pGmTime->tm_wday]);
00369       memcpy(s,r,3);
00370       s+=3;
00371       continue;
00372       }
00373 
00374     if( !memcmp(s,"WEEKDAY-NAME",12) ){
00375       len = strlen(r = WeekDayName[pGmTime->tm_wday]);
00376       memcpy(s,r,len);
00377       r = s + 12;
00378       s = s + len;
00379       len = s-r;
00380       for( ; r[len] = *r ; r++ );
00381       continue;
00382       }
00383 
00384     if( !memcmp(s,"*MONTH-NAME*",12) ){
00385       len = strlen(r = MonthName[pGmTime->tm_mon]);
00386       memcpy(s,r,len);
00387       r = s + 12;
00388       s = s + len;
00389       len = s-r;
00390       for( ; r[len] = *r ; r++ );
00391       continue;
00392       }
00393 
00394     if( !memcmp(s,"MON",3) ){
00395       len = strlen(r = MonthName[pGmTime->tm_mon]);
00396       memcpy(s,r,3);
00397       s += 3;
00398       continue;
00399       }
00400 
00401     if( !memcmp(s,"YEAR",4) ){
00402       sprintf(szNumberBuffer,"%04d",pGmTime->tm_year+1900);
00403       memcpy(s,szNumberBuffer,4);
00404       s += 4;
00405       continue;
00406       }
00407 
00408     if( !memcmp(s,"WD",2) ){
00409       *s = pGmTime->tm_wday + '0';
00410       s ++;
00411       for( r = s+1 ; r[-1] = *r ; r++ );
00412       continue;
00413       }
00414 
00415     if( !memcmp(s,"YY",2) ){
00416       sprintf(szNumberBuffer,"%04d",pGmTime->tm_year+1900);
00417       memcpy(s,szNumberBuffer+2,2);
00418       s += 2;
00419       continue;
00420       }
00421 
00422     if( !memcmp(s,"MM",2) ){
00423       if( pGmTime->tm_mon+1 < 10 ){
00424         *s = pGmTime->tm_mon+1 + '0';
00425         s ++;
00426         for( r = s+1 ; r[-1] = *r ; r++ );
00427         continue;
00428         }else{
00429         sprintf(szNumberBuffer,"%02d",pGmTime->tm_mon+1);
00430         memcpy(s,szNumberBuffer,2);
00431         s += 2;
00432         continue;
00433         }
00434       }
00435 
00436     if( !memcmp(s,"0M",2) ){
00437       sprintf(szNumberBuffer,"%02d",pGmTime->tm_mon+1);
00438       memcpy(s,szNumberBuffer,2);
00439       s += 2;
00440       continue;
00441       }
00442 
00443     if( !memcmp(s,"DD",2) ){
00444       if( pGmTime->tm_mday < 10 ){
00445         *s = pGmTime->tm_mday + '0';
00446         s ++;
00447         for( r = s+1 ; r[-1] = *r ; r++ );
00448         continue;
00449         }else{
00450         sprintf(szNumberBuffer,"%02d",pGmTime->tm_mday);
00451         memcpy(s,szNumberBuffer,2);
00452         s += 2;
00453         continue;
00454         }
00455       }
00456 
00457     if( !memcmp(s,"0D",2) ){
00458       sprintf(szNumberBuffer,"%02d",pGmTime->tm_mday);
00459       memcpy(s,szNumberBuffer,2);
00460       s += 2;
00461       continue;
00462       }
00463 
00464     if( !memcmp(s,"HH",2) ){
00465       if( pGmTime->tm_hour < 10 ){
00466         *s = pGmTime->tm_hour + '0';
00467         s ++;
00468         for( r = s+1 ; r[-1] = *r ; r++ );
00469         continue;
00470         }else{
00471         sprintf(szNumberBuffer,"%02d",pGmTime->tm_hour);
00472         memcpy(s,szNumberBuffer,2);
00473         s += 2;
00474         continue;
00475         }
00476       }
00477 
00478     if( !memcmp(s,"0H",2) ){
00479       sprintf(szNumberBuffer,"%02d",pGmTime->tm_hour);
00480       memcpy(s,szNumberBuffer,2);
00481       s += 2;
00482       continue;
00483       }
00484 
00485     if( !memcmp(s,"hh",2) ){
00486       hour = pGmTime->tm_hour;
00487       if( hour > 12 )hour -= 12;
00488       if( hour < 10 ){
00489         *s = hour + '0';
00490         s ++;
00491         for( r = s+1 ; r[-1] = *r ; r++ );
00492         continue;
00493         }else{
00494         sprintf(szNumberBuffer,"%02d",hour);
00495         memcpy(s,szNumberBuffer,2);
00496         s += 2;
00497         continue;
00498         }
00499       }
00500 
00501     if( !memcmp(s,"0h",2) ){
00502       hour = pGmTime->tm_hour;
00503       if( hour > 12 )hour -= 12;
00504       sprintf(szNumberBuffer,"%02d",hour);
00505       memcpy(s,szNumberBuffer,2);
00506       s += 2;
00507       continue;
00508       }
00509 
00510     if( !memcmp(s,"mm",2) ){
00511       if( pGmTime->tm_min < 10 ){
00512         *s = pGmTime->tm_min + '0';
00513         s ++;
00514         for( r = s+1 ; r[-1] = *r ; r++ );
00515         continue;
00516         }else{
00517         sprintf(szNumberBuffer,"%02d",pGmTime->tm_min);
00518         memcpy(s,szNumberBuffer,2);
00519         s += 2;
00520         continue;
00521         }
00522       }
00523 
00524     if( !memcmp(s,"0m",2) ){
00525       sprintf(szNumberBuffer,"%02d",pGmTime->tm_min);
00526       memcpy(s,szNumberBuffer,2);
00527       s += 2;
00528       continue;
00529       }
00530 
00531     if( !memcmp(s,"ss",2) ){
00532       if( pGmTime->tm_sec < 10 ){
00533         *s = pGmTime->tm_sec + '0';
00534         s ++;
00535         for( r = s+1 ; r[-1] = *r ; r++ );
00536         continue;
00537         }else{
00538         sprintf(szNumberBuffer,"%02d",pGmTime->tm_sec);
00539         memcpy(s,szNumberBuffer,2);
00540         s += 2;
00541         continue;
00542         }
00543       }
00544 
00545     if( !memcmp(s,"0s",2) ){
00546       sprintf(szNumberBuffer,"%02d",pGmTime->tm_sec);
00547       memcpy(s,szNumberBuffer,2);
00548       s += 2;
00549       continue;
00550       }
00551 
00552     if( (!memcmp(s,"am",2)) || (!memcmp(s,"pm",2)) ){
00553       if( pGmTime->tm_hour >= 12 )r = "pm"; else r = "am";
00554       memcpy(s,r,2);
00555       s += 2;
00556       continue;
00557       }
00558 
00559     s++;
00560     }
00561   RESULT = NEWMORTALSTRING(strlen(pszFormatString));
00562   ASSERTNULL(RESULT)
00563   memcpy(STRINGVALUE(RESULT),pszFormatString,strlen(pszFormatString));
00564 
00565 #endif
00566 END
00567 
00574 COMMAND(NOW)
00575 #if NOTIMP_NOW
00576 NOTIMPLEMENTED;
00577 #else
00578 
00579   /* this is an operator and not a command, therefore we do not have our own mortal list */
00580   USE_CALLER_MORTALS;
00581   RESULT = NEWMORTALLONG;
00582   ASSERTNULL(RESULT)
00583   LONGVALUE(RESULT) = (long)time(NULL)+ TimeDifference();
00584 #endif
00585 END
00586 
00593 COMMAND(GMTIME)
00594 #if NOTIMP_GMTIME
00595 NOTIMPLEMENTED;
00596 #else
00597 
00598   /* this is an operator and not a command, therefore we do not have our own mortal list */
00599   USE_CALLER_MORTALS;
00600   RESULT = NEWMORTALLONG;
00601   ASSERTNULL(RESULT)
00602   LONGVALUE(RESULT) = (long)time(NULL);
00603 #endif
00604 END
00605 
00606 #define NOCOMMAND(XXX) \
00607 COMMAND(XXX)\
00608 NOTIMPLEMENTED;\
00609 END
00610 
00611 #ifdef __sun
00612 #undef SEC
00613 #endif
00614 
00615 #define TIMEFUN(NAME,FIELD) \
00616 COMMAND(NAME)\
00617 \
00618  VARIABLE vTime;\
00619  time_t lTime;\
00620  NODE nItem;\
00621  struct tm *pGmTime,GmTime;\
00622 \
00623   USE_CALLER_MORTALS;\
00624   nItem = PARAMETERLIST;\
00625   if( nItem ){\
00626     vTime = EVALUATEEXPRESSION(CAR(nItem));\
00627     ASSERTOKE;\
00628   }else\
00629     vTime = NULL;\
00630 \
00631   RESULT = NEWMORTALLONG;\
00632   ASSERTNULL(RESULT)\
00633 \
00634   if( memory_IsUndef(vTime) )\
00635     lTime = (long)time(NULL)+ TimeDifference();\
00636   else\
00637     lTime = LONGVALUE(CONVERT2LONG(vTime));\
00638 \
00639   pGmTime = mygmtime(&lTime,&GmTime);\
00640   LONGVALUE(RESULT) = pGmTime->FIELD;\
00641 END
00642 
00649 #if NOTIMP_YEAR
00650 NOCOMMAND(YEAR)
00651 #else
00652 TIMEFUN(YEAR,tm_year+1900)
00653 #endif
00654 
00661 #if NOTIMP_MONTH
00662 NOCOMMAND(MONTH)
00663 #else
00664 TIMEFUN(MONTH,tm_mon+1)
00665 #endif
00666 
00673 #if NOTIMP_DAY
00674 NOCOMMAND(DAY)
00675 #else
00676 TIMEFUN(DAY,tm_mday)
00677 #endif
00678 
00685 #if NOTIMP_WDAY
00686 NOCOMMAND(WDAY)
00687 #else
00688 TIMEFUN(WDAY,tm_wday)
00689 #endif
00690 
00697 #if NOTIMP_YDAY
00698 NOCOMMAND(YDAY)
00699 #else
00700 TIMEFUN(YDAY,tm_yday)
00701 #endif
00702 
00709 #if NOTIMP_HOUR
00710 NOCOMMAND(HOUR)
00711 #else
00712 TIMEFUN(HOUR,tm_hour)
00713 #endif
00714 
00721 #if NOTIMP_MINUTE
00722 NOCOMMAND(MINUTE)
00723 #else
00724 TIMEFUN(MINUTE,tm_min)
00725 #endif
00726 
00733 #if NOTIMP_SEC
00734 NOCOMMAND(SEC)
00735 #else
00736 TIMEFUN(SEC,tm_sec)
00737 #endif
00738 
00739 #undef TIMEFUN
00740 
00741 
00757 COMMAND(TIMEVALUE)
00758 #if NOTIMP_TIMEVALUE
00759 NOTIMPLEMENTED;
00760 #else
00761 
00762   VARIABLE vTime;
00763   long lTime;
00764   NODE nItem;
00765   struct tm GmTime;
00766 
00767 /* Set the default values in case some of the parameters are missing */
00768   GmTime.tm_year = 1970;
00769   GmTime.tm_mon = 1;
00770   GmTime.tm_mday = 1;
00771   GmTime.tm_hour = 0;
00772   GmTime.tm_min = 0;
00773   GmTime.tm_sec =  0;
00774   GmTime.tm_isdst = -1;
00775 
00776   USE_CALLER_MORTALS;
00777   nItem = PARAMETERLIST;
00778   if( nItem == 0 )goto NoMoreTime;
00779 
00780 #define TAKE_ARGUMENT(x) \
00781   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));\
00782   ASSERTOKE;\
00783   if( vTime )GmTime.x = LONGVALUE(vTime);\
00784   nItem = CDR(nItem);\
00785   if( nItem == 0 )goto NoMoreTime;\
00786 
00787   TAKE_ARGUMENT(tm_year)
00788   TAKE_ARGUMENT(tm_mon)
00789   TAKE_ARGUMENT(tm_mday)
00790   TAKE_ARGUMENT(tm_hour)
00791   TAKE_ARGUMENT(tm_min)
00792   TAKE_ARGUMENT(tm_sec)
00793 
00794 NoMoreTime:;
00795   GmTime.tm_year -= 1900;
00796   GmTime.tm_mon --;
00797   lTime = mygmktime(&GmTime);
00798   if( lTime == -1 )ERROR(COMMAND_ERROR_INVALID_TIME);
00799   RESULT = NEWMORTALLONG;
00800   ASSERTNULL(RESULT)
00801   LONGVALUE(RESULT) = lTime;
00802 #endif
00803 END
00804 
00811 COMMAND(GM2LOCAL)
00812 #if NOTIMP_GM2LOCAL
00813 NOTIMPLEMENTED;
00814 #else
00815 
00816   VARIABLE vTime;
00817   long lTime;
00818   NODE nItem;
00819 
00820   USE_CALLER_MORTALS;
00821   nItem = PARAMETERLIST;
00822   if( nItem == 0 ){
00823     RESULT = NULL;
00824     RETURN;
00825     }
00826   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00827   ASSERTOKE;
00828   if( memory_IsUndef(vTime) ){
00829     RESULT = NULL;
00830     RETURN;
00831     }
00832   lTime = LONGVALUE(vTime);
00833   RESULT = NEWMORTALLONG;
00834   ASSERTNULL(RESULT)
00835   LONGVALUE(RESULT) = lTime + TimeDifference();
00836 #endif
00837 END
00838 
00845 COMMAND(LOCAL2GM)
00846 #if NOTIMP_LOCAL2GM
00847 NOTIMPLEMENTED;
00848 #else
00849 
00850   VARIABLE vTime;
00851   long lTime;
00852   NODE nItem;
00853 
00854   USE_CALLER_MORTALS;
00855   nItem = PARAMETERLIST;
00856   if( nItem == 0 ){
00857     RESULT = NULL;
00858     RETURN;
00859     }
00860   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00861   ASSERTOKE;
00862   if( memory_IsUndef(vTime) ){
00863     RESULT = NULL;
00864     RETURN;
00865     }
00866   lTime = LONGVALUE(vTime);
00867   RESULT = NEWMORTALLONG;
00868   ASSERTNULL(RESULT)
00869   LONGVALUE(RESULT) = lTime - TimeDifference();
00870 #endif
00871 END
00872 
00892 COMMAND(ADDYEAR)
00893 #if NOTIMP_ADDYEAR
00894 NOTIMPLEMENTED;
00895 #else
00896 
00897   VARIABLE vTime,vOffset;
00898   time_t lTime;
00899   NODE nItem;
00900   struct tm *pGmTime,GmTime;
00901 
00902   nItem = PARAMETERLIST;
00903   if( nItem == 0 ){
00904     RESULT = NULL;
00905     RETURN;
00906     }
00907   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00908   ASSERTOKE;
00909   nItem = CDR(nItem);
00910   vOffset = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00911   ASSERTOKE;
00912   if( memory_IsUndef(vTime) || memory_IsUndef(vOffset) ){
00913     RESULT = NULL;
00914     RETURN;
00915     }
00916   lTime = LONGVALUE(vTime);
00917   pGmTime = mygmtime(&lTime,&GmTime);
00918   pGmTime->tm_year += LONGVALUE(vOffset);
00919   /* Note that this is a very simple leap year calculation because
00920      all UNIX-es calculate time from 1970 to 2038 only.
00921      This is rubbish, but that is the way it is under UNIX. */
00922   if( pGmTime->tm_mday > 28 && pGmTime->tm_mon == 1 && (pGmTime->tm_year%4) )
00923     pGmTime->tm_mday = 28;
00924   pGmTime->tm_isdst = -1;
00925   RESULT = NEWMORTALLONG;
00926   ASSERTNULL(RESULT)
00927   LONGVALUE(RESULT) = mygmktime(&GmTime);
00928 #endif
00929 END
00930 
00949 COMMAND(ADDMONTH)
00950 #if NOTIMP_ADDMONTH
00951 NOTIMPLEMENTED;
00952 #else
00953 
00954   VARIABLE vTime,vOffset;
00955   time_t lTime;
00956   NODE nItem;
00957   struct tm *pGmTime,GmTime;
00958 
00959   nItem = PARAMETERLIST;
00960   if( nItem == 0 ){
00961     RESULT = NULL;
00962     RETURN;
00963     }
00964   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00965   ASSERTOKE;
00966   nItem = CDR(nItem);
00967   vOffset = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));
00968   ASSERTOKE;
00969   if( memory_IsUndef(vTime) || memory_IsUndef(vOffset) ){
00970     RESULT = NULL;
00971     RETURN;
00972     }
00973   lTime = LONGVALUE(vTime);
00974   pGmTime = mygmtime(&lTime,&GmTime);
00975   pGmTime->tm_mon += LONGVALUE(vOffset);
00976   if( pGmTime->tm_mday == 31 && (pGmTime->tm_mon == 3 ||
00977                                  pGmTime->tm_mon == 5 ||
00978                                  pGmTime->tm_mon == 7 ||
00979                                  pGmTime->tm_mon == 8 ||
00980                                  pGmTime->tm_mon == 10 ))
00981     pGmTime->tm_mday = 30;
00982   if( pGmTime->tm_mday > 29 && pGmTime->tm_mon == 1 )
00983     pGmTime->tm_mday = 29;
00984   /* Note that this is a very simple leap year calculation because
00985      all UNIX-es calculate time from 1970 to 2038 only.
00986      This is rubbish, but that the way it is under UNIX. */
00987   if( pGmTime->tm_mday > 28 && pGmTime->tm_mon == 1 && (pGmTime->tm_year%4) )
00988     pGmTime->tm_mday = 28;
00989 
00990   pGmTime->tm_isdst = -1;
00991   RESULT = NEWMORTALLONG;
00992   ASSERTNULL(RESULT)
00993   LONGVALUE(RESULT) = mygmktime(&GmTime);
00994 #endif
00995 END
00996 
00997 
00998 #undef TIMEFUN
00999 #define TIMEFUN(XXX,YYY) \
01000 COMMAND(XXX)\
01001   VARIABLE vTime,vOffset;\
01002   long lTime;\
01003   NODE nItem;\
01004 \
01005   nItem = PARAMETERLIST;\
01006   if( nItem == 0 ){\
01007     RESULT = NULL;\
01008     RETURN;\
01009     }\
01010   vTime = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));\
01011   ASSERTOKE;\
01012   nItem = CDR(nItem);\
01013   vOffset = CONVERT2LONG(EVALUATEEXPRESSION(CAR(nItem)));\
01014   ASSERTOKE;\
01015   if( memory_IsUndef(vTime) || memory_IsUndef(vOffset) ){\
01016     RESULT = NULL;\
01017     RETURN;\
01018     }\
01019   lTime = LONGVALUE(vTime);\
01020   RESULT = NEWMORTALLONG;\
01021   ASSERTNULL(RESULT)\
01022   LONGVALUE(RESULT) = lTime + LONGVALUE(vOffset)*YYY;\
01023 END
01024 
01033 #if NOTIMP_ADDWEEK
01034 NOCOMMAND(ADDWEEK)
01035 #else
01036 TIMEFUN(ADDWEEK,604800)
01037 #endif
01038 
01047 #if NOTIMP_ADDDAY
01048 NOCOMMAND(ADDDAY)
01049 #else
01050 TIMEFUN(ADDDAY,86400)
01051 #endif
01052 
01061 #if NOTIMP_ADDHOUR
01062 NOCOMMAND(ADDHOUR)
01063 #else
01064 TIMEFUN(ADDHOUR,3600)
01065 #endif
01066 
01075 #if NOTIMP_ADDMINUTE
01076 NOCOMMAND(ADDMINUTE)
01077 #else
01078 TIMEFUN(ADDMINUTE,60)
01079 #endif
01080 
01089 #if NOTIMP_ADDSECOND
01090 NOCOMMAND(ADDSECOND)
01091 #else
01092 TIMEFUN(ADDSECOND,1);
01093 #endif
01094 
01095 #undef TIMEFUN

Generated on Sun Mar 12 23:56:27 2006 for ScriptBasic by  doxygen 1.4.6-NO