Root/plasma/kernel/libc.c

1/*--------------------------------------------------------------------
2 * TITLE: ANSI C Library
3 * AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 * DATE CREATED: 12/17/05
5 * FILENAME: libc.c
6 * PROJECT: Plasma CPU core
7 * COPYRIGHT: Software placed into the public domain by the author.
8 * Software 'as is' without warranty. Author liable for nothing.
9 * DESCRIPTION:
10 * Subset of the ANSI C library
11 *--------------------------------------------------------------------*/
12#define NO_ELLIPSIS
13#include "rtos.h"
14
15
16char *strcpy(char *dst, const char *src)
17{
18   char *dstSave=dst;
19   int c;
20   do
21   {
22      c = *dst++ = *src++;
23   } while(c);
24   return dstSave;
25}
26
27
28char *strncpy(char *dst, const char *src, int count)
29{
30   int c=1;
31   char *dstSave=dst;
32   while(count-- > 0 && c)
33      c = *dst++ = *src++;
34   *dst = 0;
35   return dstSave;
36}
37
38
39char *strcat(char *dst, const char *src)
40{
41   int c;
42   char *dstSave=dst;
43   while(*dst)
44      ++dst;
45   do
46   {
47      c = *dst++ = *src++;
48   } while(c);
49   return dstSave;
50}
51
52
53char *strncat(char *dst, const char *src, int count)
54{
55   int c=1;
56   char *dstSave=dst;
57   while(*dst && --count > 0)
58      ++dst;
59   while(--count > 0 && c)
60      c = *dst++ = *src++;
61   *dst = 0;
62   return dstSave;
63}
64
65
66int strcmp(const char *string1, const char *string2)
67{
68   int diff, c;
69   for(;;)
70   {
71      diff = *string1++ - (c = *string2++);
72      if(diff)
73         return diff;
74      if(c == 0)
75         return 0;
76   }
77}
78
79
80int strncmp(const char *string1, const char *string2, int count)
81{
82   int diff, c;
83   while(count-- > 0)
84   {
85      diff = *string1++ - (c = *string2++);
86      if(diff)
87         return diff;
88      if(c == 0)
89         return 0;
90   }
91   return 0;
92}
93
94
95char *strstr(const char *string, const char *find)
96{
97   int i;
98   for(;;)
99   {
100      for(i = 0; string[i] == find[i] && find[i]; ++i) ;
101      if(find[i] == 0)
102         return (char*)string;
103      if(*string++ == 0)
104         return NULL;
105   }
106}
107
108
109int strlen(const char *string)
110{
111   const char *base=string;
112   while(*string++) ;
113   return string - base - 1;
114}
115
116
117void *memcpy(void *dst, const void *src, unsigned long bytes)
118{
119   if(((uint32)dst | (uint32)src | bytes) & 3)
120   {
121      uint8 *Dst = (uint8*)dst, *Src = (uint8*)src;
122      while((int)bytes-- > 0)
123         *Dst++ = *Src++;
124   }
125   else
126   {
127      uint32 *Dst32 = (uint32*)dst, *Src32 = (uint32*)src;
128      bytes >>= 2;
129      while((int)bytes-- > 0)
130         *Dst32++ = *Src32++;
131   }
132   return dst;
133}
134
135
136void *memmove(void *dst, const void *src, unsigned long bytes)
137{
138   uint8 *Dst = (uint8*)dst;
139   uint8 *Src = (uint8*)src;
140   if(Dst < Src)
141   {
142      while((int)bytes-- > 0)
143         *Dst++ = *Src++;
144   }
145   else
146   {
147      Dst += bytes;
148      Src += bytes;
149      while((int)bytes-- > 0)
150         *--Dst = *--Src;
151   }
152   return dst;
153}
154
155
156int memcmp(const void *cs, const void *ct, unsigned long bytes)
157{
158   uint8 *Dst = (uint8*)cs;
159   uint8 *Src = (uint8*)ct;
160   int diff;
161   while((int)bytes-- > 0)
162   {
163      diff = *Dst++ - *Src++;
164      if(diff)
165         return diff;
166   }
167   return 0;
168}
169
170
171void *memset(void *dst, int c, unsigned long bytes)
172{
173   uint8 *Dst = (uint8*)dst;
174   while((int)bytes-- > 0)
175      *Dst++ = (uint8)c;
176   return dst;
177}
178
179
180int abs(int n)
181{
182   return n>=0 ? n : -n;
183}
184
185
186static uint32 Rand1=0x1f2bcda3, Rand2=0xdeafbeef, Rand3=0xc5134306;
187int rand(void)
188{
189   int shift;
190   Rand1 += 0x13423123 + Rand2;
191   Rand2 += 0x2312fdea + Rand3;
192   Rand3 += 0xf2a12de1;
193   shift = Rand3 & 31;
194   Rand1 = (Rand1 << (32 - shift)) | (Rand1 >> shift);
195   Rand3 ^= Rand1;
196   shift = (Rand3 >> 8) & 31;
197   Rand2 = (Rand2 << (32 - shift)) | (Rand2 >> shift);
198   return Rand1;
199}
200
201
202void srand(unsigned int seed)
203{
204   Rand1 = seed;
205}
206
207
208long strtol(const char *s, char **end, int base)
209{
210   int i;
211   unsigned long ch, value=0, neg=0;
212
213   if(s[0] == '-')
214   {
215      neg = 1;
216      ++s;
217   }
218   if(s[0] == '0' && s[1] == 'x')
219   {
220      base = 16;
221      s += 2;
222   }
223   for(i = 0; i <= 8; ++i)
224   {
225      ch = *s++;
226      if('0' <= ch && ch <= '9')
227         ch -= '0';
228      else if('A' <= ch && ch <= 'Z')
229         ch = ch - 'A' + 10;
230      else if('a' <= ch && ch <= 'z')
231         ch = ch - 'a' + 10;
232      else
233         break;
234      value = value * base + ch;
235   }
236   if(end)
237      *end = (char*)s - 1;
238   if(neg)
239      value = -(int)value;
240   return value;
241}
242
243
244int atoi(const char *s)
245{
246   return strtol(s, NULL, 10);
247}
248
249
250char *itoa(int num, char *dst, int base)
251{
252   int digit, negate=0, place;
253   char c, text[20];
254
255   if(base == 10 && num < 0)
256   {
257      num = -num;
258      negate = 1;
259   }
260   text[16] = 0;
261   for(place = 15; place >= 0; --place)
262   {
263      digit = (unsigned int)num % (unsigned int)base;
264      if(num == 0 && place < 15 && base == 10 && negate)
265      {
266         c = '-';
267         negate = 0;
268      }
269      else if(digit < 10)
270         c = (char)('0' + digit);
271      else
272         c = (char)('a' + digit - 10);
273      text[place] = c;
274      num = (unsigned int)num / (unsigned int)base;
275      if(num == 0 && negate == 0)
276         break;
277   }
278   strcpy(dst, text + place);
279   return dst;
280}
281
282
283int sprintf(char *s, const char *format,
284            int arg0, int arg1, int arg2, int arg3,
285            int arg4, int arg5, int arg6, int arg7)
286{
287   int argv[8];
288   int argc=0, width, length;
289   char f, text[20], fill;
290
291   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
292   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
293
294   for(;;)
295   {
296      f = *format++;
297      if(f == 0)
298         return argc;
299      else if(f == '%')
300      {
301         width = 0;
302         fill = ' ';
303         f = *format++;
304         while('0' <= f && f <= '9')
305         {
306            width = width * 10 + f - '0';
307            f = *format++;
308         }
309         if(f == '.')
310         {
311            fill = '0';
312            f = *format++;
313         }
314         if(f == 0)
315            return argc;
316
317         if(f == 'd')
318         {
319            memset(s, fill, width);
320            itoa(argv[argc++], text, 10);
321            length = (int)strlen(text);
322            if(width < length)
323               width = length;
324            strcpy(s + width - length, text);
325         }
326         else if(f == 'x' || f == 'f')
327         {
328            memset(s, '0', width);
329            itoa(argv[argc++], text, 16);
330            length = (int)strlen(text);
331            if(width < length)
332               width = length;
333            strcpy(s + width - length, text);
334         }
335         else if(f == 'c')
336         {
337            *s++ = (char)argv[argc++];
338            *s = 0;
339         }
340         else if(f == 's')
341         {
342            length = strlen((char*)argv[argc]);
343            if(width > length)
344            {
345               memset(s, ' ', width - length);
346               s += width - length;
347            }
348            strcpy(s, (char*)argv[argc++]);
349         }
350         s += strlen(s);
351      }
352      else
353      {
354         if(f == '\n')
355            *s++ = '\r';
356         *s++ = f;
357         if(f == '\r' && *format == '\n')
358            *s++ = *format++;
359      }
360      *s = 0;
361   }
362}
363
364
365int sscanf(const char *s, const char *format,
366           int arg0, int arg1, int arg2, int arg3,
367           int arg4, int arg5, int arg6, int arg7)
368{
369   int argv[8];
370   int argc=0;
371   char f, *ptr;
372
373   argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
374   argv[4] = arg4; argv[5] = arg5; argv[6] = arg6; argv[7] = arg7;
375
376   for(;;)
377   {
378      if(*s == 0)
379         return argc;
380      f = *format++;
381      if(f == 0)
382         return argc;
383      else if(f == '%')
384      {
385         while(isspace(*s))
386            ++s;
387         f = *format++;
388         if(f == 0)
389            return argc;
390         if(f == 'd')
391            *(int*)argv[argc++] = strtol(s, (char**)&s, 10);
392         else if(f == 'x')
393            *(int*)argv[argc++] = strtol(s, (char**)&s, 16);
394         else if(f == 'c')
395            *(char*)argv[argc++] = *s++;
396         else if(f == 's')
397         {
398            ptr = (char*)argv[argc++];
399            while(!isspace(*s))
400               *ptr++ = *s++;
401            *ptr = 0;
402         }
403      }
404      else
405      {
406         while(*s && *s != f)
407            ++s;
408         if(*s)
409            ++s;
410      }
411   }
412}
413
414
415#ifdef INCLUDE_DUMP
416/*********************** dump ***********************/
417void dump(const unsigned char *data, int length)
418{
419   int i, index=0, value;
420   char string[80];
421   memset(string, 0, sizeof(string));
422   for(i = 0; i < length; ++i)
423   {
424      if((i & 15) == 0)
425      {
426         if(strlen(string))
427            printf("%s\n", string);
428         printf("%4x ", i);
429         memset(string, 0, sizeof(string));
430         index = 0;
431      }
432      value = data[i];
433      printf("%2x ", value);
434      if(isprint(value))
435         string[index] = (char)value;
436      else
437         string[index] = '.';
438      ++index;
439   }
440   for(; index < 16; ++index)
441      printf(" ");
442   printf("%s\n", string);
443}
444#endif //INCLUDE_DUMP
445
446
447#ifdef INCLUDE_QSORT
448/*********************** qsort ***********************/
449static void QsortSwap(char *base, long left, long right, long size)
450{
451   int temp, i;
452   char *ptrLeft, *ptrRight;
453   ptrLeft = base + left * size;
454   ptrRight = base + right * size;
455   for(i = 0; i < size; ++i)
456   {
457      temp = ptrLeft[i];
458      ptrLeft[i] = ptrRight[i];
459      ptrRight[i] = (char)temp;
460   }
461}
462
463
464//Modified from K&R
465static void qsort2(void *base, long left, long right, long size,
466      int (*cmp)(const void *,const void *))
467{
468   int i, last;
469   char *base2=(char*)base, *pivot;
470   if(left >= right)
471      return;
472   QsortSwap(base2, left, (left + right)/2, size);
473   last = left;
474   pivot = &base2[left*size];
475   for(i = left + 1; i <= right; ++i)
476   {
477      if(cmp(&base2[i*size], pivot) < 0)
478         QsortSwap(base2, ++last, i, size);
479   }
480   QsortSwap(base2, left, last, size);
481   qsort2(base, left, last-1, size, cmp);
482   qsort2(base, last+1, right, size, cmp);
483}
484
485
486void qsort(void *base,
487           long n,
488           long size,
489           int (*cmp)(const void *,const void *))
490{
491   qsort2(base, 0, n-1, size, cmp);
492}
493
494
495void *bsearch(const void *key,
496              const void *base,
497              long n,
498              long size,
499              int (*cmp)(const void *,const void *))
500{
501   long cond, low=0, high=n-1, mid;
502   char *base2=(char*)base;
503   while(low <= high)
504   {
505      mid = (low + high)/2;
506      cond = cmp(key, &base2[mid*size]);
507      if(cond < 0)
508         high = mid - 1;
509      else if(cond > 0)
510         low = mid + 1;
511      else
512         return &base2[mid * size];
513   }
514   return NULL;
515}
516#endif //INCLUDE_QSORT
517
518
519#ifdef INCLUDE_TIMELIB
520/************************* time.h ***********************/
521#define SEC_PER_YEAR (365L*24*60*60)
522#define SEC_PER_DAY (24L*60*60)
523//typedef unsigned long time_t; //start at 1/1/80
524//struct tm {
525// int tm_sec; //(0,59)
526// int tm_min; //(0,59)
527// int tm_hour; //(0,23)
528// int tm_mday; //(1,31)
529// int tm_mon; //(0,11)
530// int tm_year; //(0,n) from 1900
531// int tm_wday; //(0,6) calculated
532// int tm_yday; //(0,365) calculated
533// int tm_isdst; //hour adjusted for day light savings
534//};
535static const unsigned short DaysUntilMonth[]=
536   {0,31,59,90,120,151,181,212,243,273,304,334,365};
537static const unsigned short DaysInMonth[]=
538   {31,28,31,30,31,30,31,31,30,31,30,31};
539static time_t DstTimeIn, DstTimeOut;
540
541
542/* Leap year if divisible by 4. Centenary years should only be
543   leap-years if they were divisible by 400. */
544static int IsLeapYear(int year)
545{
546   return(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
547}
548
549time_t mktime(struct tm *tp)
550{
551   time_t seconds;
552   unsigned long days, y, year;
553
554   days = tp->tm_mday - 1 + DaysUntilMonth[tp->tm_mon] +
555      365 * (tp->tm_year - 80);
556   seconds = (unsigned long)tp->tm_sec + 60L * (tp->tm_min +
557      60L * (tp->tm_hour + 24L * days));
558   if(tp->tm_isdst)
559      seconds -= 60 * 60;
560   year = 1900 + tp->tm_year - (tp->tm_mon < 2);
561   for(y = 1980; y <= year; y += 4)
562   {
563      if(y % 100 != 0 || y % 400 == 0)
564         seconds += SEC_PER_DAY;
565   }
566   return seconds;
567}
568
569
570void gmtime_r(const time_t *tp, struct tm *out)
571{
572   time_t seconds, delta, secondsIn=*tp;
573   int isLeapYear;
574   unsigned long year, month;
575
576   out->tm_isdst = 0;
577   if(DstTimeIn <= secondsIn && secondsIn < DstTimeOut)
578   {
579      secondsIn += 60 * 60;
580      out->tm_isdst = 1;
581   }
582   seconds = secondsIn;
583   for(year = 0; ; ++year)
584   {
585      delta = SEC_PER_YEAR + IsLeapYear(1980 + year) * SEC_PER_DAY;
586      if(seconds >= delta)
587         seconds -= delta;
588      else
589         break;
590   }
591   out->tm_year = year + 80;
592   isLeapYear = IsLeapYear(1980 + year);
593   for(month = 0; ; ++month)
594   {
595      delta = SEC_PER_DAY * (DaysInMonth[month] + (isLeapYear && (month == 1)));
596      if(seconds >= delta)
597         seconds -= delta;
598      else
599         break;
600   }
601   out->tm_mon = month;
602   out->tm_mday = seconds / SEC_PER_DAY;
603   out->tm_yday = DaysUntilMonth[month] + out->tm_mday;
604   seconds -= out->tm_mday * SEC_PER_DAY;
605   ++out->tm_mday;
606   out->tm_hour = seconds / (60 * 60);
607   seconds -= out->tm_hour * (60 * 60);
608   out->tm_min = seconds / 60;
609   seconds -= out->tm_min * 60;
610   out->tm_sec = seconds;
611   seconds = secondsIn % (SEC_PER_DAY * 7);
612   out->tm_wday = (seconds / SEC_PER_DAY + 2) % 7; /* 1/1/80 is a Tue */
613   //printf("%4.d/%2.d/%2.d:%2.d:%2.d:%2.d\n",
614   // out->tm_year+1900, out->tm_mon+1, out->tm_mday,
615   // out->tm_hour, out->tm_min, out->tm_sec);
616}
617
618
619void gmtimeDst(time_t dstTimeIn, time_t dstTimeOut)
620{
621   DstTimeIn = dstTimeIn;
622   DstTimeOut = dstTimeOut;
623}
624
625
626//DST from 2am on the second Sunday in March to 2am first Sunday in November
627void gmtimeDstSet(time_t *tp, time_t *dstTimeIn, time_t *dstTimeOut)
628{
629   time_t seconds, timeIn, timeOut;
630   struct tm tmDate;
631   int year, days;
632
633   DstTimeIn = 0;
634   DstTimeOut = 0;
635   gmtime_r(tp, &tmDate);
636   year = tmDate.tm_year;
637
638   //March 1, year, 2AM -> second Sunday
639   tmDate.tm_year = year;
640   tmDate.tm_mon = 2;
641   tmDate.tm_mday = 1;
642   tmDate.tm_hour = 2;
643   tmDate.tm_min = 0;
644   tmDate.tm_sec = 0;
645   seconds = mktime(&tmDate);
646   gmtime_r(&seconds, &tmDate);
647   days = 7 - tmDate.tm_wday + 7;
648   *dstTimeIn = timeIn = seconds + days * SEC_PER_DAY;
649
650   //November 1, year, 2AM -> first Sunday
651   tmDate.tm_year = year;
652   tmDate.tm_mon = 10;
653   tmDate.tm_mday = 1;
654   tmDate.tm_hour = 2;
655   tmDate.tm_min = 0;
656   tmDate.tm_sec = 0;
657   seconds = mktime(&tmDate);
658   gmtime_r(&seconds, &tmDate);
659   days = 7 - tmDate.tm_wday;
660   *dstTimeOut = timeOut = seconds + days * SEC_PER_DAY;
661
662   DstTimeIn = timeIn;
663   DstTimeOut = timeOut;
664}
665#endif //INCLUDE_TIMELIB
666
667

Archive Download this file

Branches:
master



interactive