src/compat.c

Go to the documentation of this file.
00001 /*
00002  * compat.c -- functions that we need to provide because they are missing 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #ifdef NEED_TIMELOCAL
00009 
00010 #define altzone         ((time_t)(timezone + 3600))
00011 
00012 /*
00013  * CAUTION: side effects 
00014  */
00015 #define is_leap(x)      (((!((x)%4)&&(x)%100)||!(((x)+1900)%400))?1:0)
00016 
00017 static int yday_size[2][12] = {
00018         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
00019         {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
00020 };
00021 
00022 static int mon_size[2][12] = {
00023         {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00024         {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
00025 };
00026 
00027 /*
00028  * e.g: normalize(&tm_secs, &tm_hour, 60); 
00029  */
00030 static void normalize(int *x, int *y, int f)
00031 {
00032         if(*x >= f) {
00033                 *y += *x / f;
00034                 *x %= f;
00035         }
00036         /*
00037          * can't rely on modulus for negative numbers 
00038          */
00039 
00040         while (*x < 0) {
00041                 *x += f;
00042                 (*y)--;
00043         }
00044 }
00045 
00046 time_t timelocal(struct tm *tp)
00047 {
00048         long unsigned k;
00049         struct tm tm;
00050         time_t t, t1;
00051 
00052         tzset();                                        /*
00053                                                                  * set up time zone 
00054                                                                  */
00055 
00056         /*
00057          * normalize the time 
00058          */
00059         normalize(&tp->tm_sec, &tp->tm_min, 60);
00060         normalize(&tp->tm_min, &tp->tm_hour, 60);
00061         normalize(&tp->tm_hour, &tp->tm_mday, 24);
00062 
00063         /*
00064          * normalize the month first 
00065          */
00066         normalize(&tp->tm_mon, &tp->tm_year, 12);
00067 
00068         /*
00069          * days to months a little tricky 
00070          */
00071         while (tp->tm_mday < 1) {
00072                 if(--tp->tm_mon < 0) {
00073                         tp->tm_year--;
00074                         tp->tm_mon += 12;
00075                 }
00076                 tp->tm_mday += mon_size[is_leap(tp->tm_year)][tp->tm_mon];
00077         }
00078 
00079         while (tp->tm_mday > (k = mon_size[is_leap(tp->tm_year)][tp->tm_mon])) {
00080                 tp->tm_mday -= k;
00081 
00082                 if(++tp->tm_mon > 12) {
00083                         tp->tm_year++;
00084                         tp->tm_mon -= 12;
00085                 }
00086         }
00087 
00088         k = tp->tm_year / 4;            /*
00089                                                                  * number of 4 year groups 
00090                                                                  */
00091         t = (k * 1461) - 1;                     /*
00092                                                                  * number of days 
00093                                                                  */
00094         k = tp->tm_year % 4;            /*
00095                                                                  * number of years beyond group 
00096                                                                  */
00097         t += (k * 365);                         /*
00098                                                                  * add number of days 
00099                                                                  */
00100         if(k)                                           /*
00101                                                                  * * if not group break year  
00102                                                                  */
00103                 t++;                                    /*
00104                                                                  * add one day 
00105                                                                  */
00106 
00107         /*
00108          * Since the epoch starts at Jan 1/70, we have to subtract the * of * 
00109          * 
00110          * *  * *  * *  * * days from Jan 1/00.  This is actually 25567 days. 
00111          * See  * * * below * for  *  * * the explanation of the discrepancy 
00112          */
00113 
00114         t -= 25568;                                     /*
00115                                                                  * t = # days to 00:00:00 Jan 1/70 
00116                                                                  */
00117         t += yday_size[is_leap(tp->tm_year)][tp->tm_mon];
00118 
00119         /*
00120          * Add the number of days in month.  Note that we should really * * * 
00121          * 
00122          * *  * *  * * subtract 1 from the day first but we effectively did
00123          * this * * * above * * * when we subtracted an extra day (25568
00124          * instead of * * 25567) 
00125          */
00126 
00127         t += tp->tm_mday;                       /*
00128                                                                  * # days to given day at 00:00:00 
00129                                                                  */
00130 
00131         /*
00132          * now add in the number of seconds in the day 
00133          */
00134 
00135         t = (t * 24) + tp->tm_hour;
00136         t = (t * 60) + tp->tm_min;
00137         t = (t * 60) + tp->tm_sec;      /*
00138                                                                  * total number of seconds 
00139                                                                  */
00140 
00141         /*
00142          * if caller thinks he/she knows what time zone then believe them 
00143          */
00144 
00145         if(tp->tm_isdst == 0)
00146                 t += timezone;
00147         else if(tp->tm_isdst > 0)
00148                 t += altzone;
00149         else {
00150                 /*
00151                  * we have to figure it out, guess dst first 
00152                  */
00153 
00154                 t1 = t + altzone;
00155                 tm = *localtime(&t1);
00156 
00157                 /*
00158                  * see if the guess matches the reality 
00159                  */
00160 
00161                 if(tm.tm_hour == tp->tm_hour && tm.tm_min == tp->tm_min)
00162                         t = t1;
00163                 else {
00164 
00165 #ifdef CHECK_INVALID
00166 
00167                         /*
00168                          * if CHECK_INVALID is defined then we attempt to * * 
00169                          * 
00170                          * *  * *  * *  * * check for the invalid time case
00171                          * e.g. a  * time  * of *  * *  * 0230h on the first
00172                          * sunday in * April * will * return -1 * * * -
00173                          * personally I * don't think * this is  * polite * * 
00174                          * behaviour 
00175                          */
00176 
00177                         t1 = t + timezone;
00178                         tm = *localtime(&t1);
00179 
00180                         if((tm.tm_hour == tp->tm_hour) && (tm.tm_min == tp->tm_min))
00181                                 t = t1;
00182                         else
00183                                 return (-1);
00184 #else
00185                         t += timezone;
00186 #endif
00187                 }
00188         }
00189 
00190         *tp = *localtime(&t);           /*
00191                                                                  * set other fields in structure 
00192                                                                  */
00193         return (t);
00194 }
00195 
00196 #endif /*
00197             * * NEED_TIMELOCAL  
00198             */
00199 
00200 /*
00201  * Need strnlen
00202  */
00203 
00204 #ifndef HAVE_STRNLEN
00205 size_t strnlen(const char *s, size_t maxlen)
00206 {
00207 
00208         int count;
00209 
00210         for(count = 0; count < maxlen && s[count] != '\x0'; count++);
00211 
00212         return count;
00213 
00214 }
00215 #endif
00216 
00217 /*
00218  * Need strndup
00219  */
00220 #ifndef HAVE_STRNDUP
00221 char *strndup(const char *s, size_t n)
00222 {
00223         int length;
00224         char *buf;
00225 
00226         length = strnlen(s, n);
00227         buf = malloc(length + 1);
00228         memset(buf, '\0', length + 1);
00229         strncpy(buf, s, length);
00230 
00231         return buf;
00232 }
00233 #endif
00234 
00235 #ifndef HAVE_STRLCPY
00236 size_t strlcpy(char *dst, const char *src, size_t len) {
00237     int iter = len - 1;
00238 
00239     if(len == 0) return strlen(src);
00240 
00241     while(iter--) {
00242         if((*dst++ = *src++) == 0)
00243             break;
00244     }
00245     if(iter < 1) *dst = 0;
00246     return (len - iter);
00247 }
00248 #endif
00249 #ifndef HAVE_STRLCAT
00250 size_t strlcat(char *dst, const char *src, size_t len) {
00251     int iter = len - 1;
00252 
00253     if(len == 0) return strlen(src);
00254 
00255     while(iter && *dst) {
00256         iter--; dst++;
00257     }
00258 
00259     if(!iter)
00260         return len+strlen(src);
00261 
00262     while(iter--) {
00263         if((*dst++ = *src++) == 0)
00264             break;
00265     }
00266     if(iter < 1) *dst = 0;
00267 
00268     return (len - iter);
00269 }
00270 #endif
00271 

Generated on Mon May 28 04:25:19 2007 for BattletechMUX by  doxygen 1.4.7