66c966036fa692954f97a76313f54df1b3670ae3
[tpg/acess2.git] / Kernel / lib.c
1 /*
2  * Acess2
3  * Common Library Functions
4  */
5 #include <acess.h>
6
7 // === CONSTANTS ===
8 #define RANDOM_SEED     0xACE55052
9 #define RANDOM_A        0x00731ADE
10 #define RANDOM_C        12345
11 #define RANDOM_SPRUCE   0xf12b039
12 //                          Jan Feb Mar Apr May  Jun  Jul  Aug  Sept Oct  Nov  Dec
13 const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
14 #define UNIX_TO_2K      ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
15
16 // === PROTOTYPES ===
17  int    atoi(const char *string);
18 void    itoa(char *buf, Uint num, int base, int minLength, char pad);
19  int    vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
20  int    sprintf(char *__s, const char *__format, ...);
21  int    tolower(int c);
22  int    strucmp(const char *Str1, const char *Str2);
23  int    strpos(const char *Str, char Ch);
24  Uint8  ByteSum(void *Ptr, int Size);
25 size_t  strlen(const char *__s);
26 char    *strcpy(char *__str1, const char *__str2);
27 char    *strncpy(char *__str1, const char *__str2, size_t max);
28  int    strcmp(const char *str1, const char *str2);
29  int    strncmp(const char *str1, const char *str2, size_t num);
30 char    *_strdup(const char *File, int Line, const char *Str);
31 char    **str_split(const char *__str, char __ch);
32  int    strpos8(const char *str, Uint32 Search);
33  int    ReadUTF8(Uint8 *str, Uint32 *Val);
34  int    WriteUTF8(Uint8 *str, Uint32 Val);
35  int    DivUp(int num, int dem);
36 Sint64  timestamp(int sec, int mins, int hrs, int day, int month, int year);
37 Uint    rand(void);
38  int    CheckString(char *String);
39  int    CheckMem(void *Mem, int NumBytes);
40  int    ModUtil_LookupString(char **Array, char *Needle);
41  int    ModUtil_SetIdent(char *Dest, char *Value);
42
43 // === EXPORTS ===
44 EXPORT(atoi);
45 EXPORT(itoa);
46 EXPORT(vsnprintf);
47 EXPORT(sprintf);
48 EXPORT(tolower);
49 EXPORT(strucmp);
50 EXPORT(strpos);
51 EXPORT(ByteSum);
52 EXPORT(strlen);
53 EXPORT(strcpy);
54 EXPORT(strncpy);
55 EXPORT(strcmp);
56 EXPORT(strncmp);
57 //EXPORT(strdup);
58 EXPORT(_strdup);        // Takes File/Line too
59 EXPORT(str_split);
60 EXPORT(strpos8);
61 EXPORT(DivUp);
62 EXPORT(ReadUTF8);
63 EXPORT(WriteUTF8);
64 EXPORT(timestamp);
65 EXPORT(CheckString);
66 EXPORT(CheckMem);
67 EXPORT(ModUtil_LookupString);
68 EXPORT(ModUtil_SetIdent);
69
70 // === CODE ===
71 /**
72  * \brief Convert a string into an integer
73  */
74 int atoi(const char *string)
75 {
76          int    ret = 0;
77          int    bNeg = 0;
78         
79         //Log("atoi: (string='%s')", string);
80         
81         // Clear non-numeric characters
82         while( !('0' <= *string && *string <= '9') && *string != '-' )  string++;
83         if( *string == '-' ) {
84                 bNeg = 1;
85                 while( !('0' <= *string && *string <= '9') )    string++;
86         }
87         
88         if(*string == '0')
89         {
90                 string ++;
91                 if(*string == 'x')
92                 {
93                         // Hex
94                         string ++;
95                         for( ;; string ++ )
96                         {
97                                 if('0' <= *string && *string <= '9') {
98                                         ret *= 16;
99                                         ret += *string - '0';
100                                 }
101                                 else if('A' <= *string && *string <= 'F') {
102                                         ret *= 16;
103                                         ret += *string - 'A' + 10;
104                                 }
105                                 else if('a' <= *string && *string <= 'f') {
106                                         ret *= 16;
107                                         ret += *string - 'a' + 10;
108                                 }
109                                 else
110                                         break;
111                         }
112                 }
113                 else    // Octal
114                 {
115                         for( ; '0' <= *string && *string <= '7'; string ++ )
116                         {
117                                 ret *= 8;
118                                 ret += *string - '0';
119                         }
120                 }
121         }
122         else    // Decimal
123         {
124                 for( ; '0' <= *string && *string <= '9'; string++)
125                 {
126                         ret *= 10;
127                         ret += *string - '0';
128                 }
129         }
130         
131         if(bNeg)        ret = -ret;
132         
133         //Log("atoi: RETURN %i", ret);
134         
135         return ret;
136 }
137
138 static const char cUCDIGITS[] = "0123456789ABCDEF";
139 /**
140  * \fn void itoa(char *buf, Uint num, int base, int minLength, char pad)
141  * \brief Convert an integer into a character string
142  */
143 void itoa(char *buf, Uint num, int base, int minLength, char pad)
144 {
145         char    tmpBuf[BITS];
146          int    pos=0, i;
147
148         // Sanity check
149         if(!buf)        return;
150         
151         // Sanity Check
152         if(base > 16 || base < 2) {
153                 buf[0] = 0;
154                 return;
155         }
156         
157         // Convert 
158         while(num > base-1) {
159                 tmpBuf[pos] = cUCDIGITS[ num % base ];
160                 num /= (Uint)base;              // Shift `num` right 1 digit
161                 pos++;
162         }
163         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of `num`
164         
165         // Put in reverse
166         i = 0;
167         minLength -= pos;
168         while(minLength-- > 0)  buf[i++] = pad;
169         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters
170         buf[i] = 0;
171 }
172
173 /**
174  * \brief Append a character the the vsnprintf output
175  */
176 #define PUTCH(c)        do{\
177         char ch=(c);\
178         if(pos==__maxlen){return pos;}\
179         if(__s){__s[pos++]=ch;}else{pos++;}\
180         }while(0)
181 #define GETVAL()        do {\
182         if(isLongLong)  val = va_arg(args, Uint64);\
183         else    val = va_arg(args, unsigned int);\
184         }while(0)
185 /**
186  * \brief VArg String Number Print Formatted
187  */
188 int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
189 {
190         char    c, pad = ' ';
191          int    minSize = 0, len;
192         char    tmpBuf[34];     // For Integers
193         char    *p = NULL;
194          int    isLongLong = 0;
195         Uint64  val;
196         size_t  pos = 0;
197         // Flags
198          int    bPadLeft = 0;
199         
200         //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
201         
202         while((c = *__format++) != 0)
203         {
204                 // Non control character
205                 if(c != '%') { PUTCH(c); continue; }
206                 
207                 c = *__format++;
208                 //Log("pos = %i", pos);
209                 
210                 // Literal %
211                 if(c == '%') { PUTCH('%'); continue; }
212                 
213                 // Pointer - Done first for debugging
214                 if(c == 'p') {
215                         Uint    ptr = va_arg(args, Uint);
216                         PUTCH('*');     PUTCH('0');     PUTCH('x');
217                         p = tmpBuf;
218                         itoa(p, ptr, 16, BITS/4, '0');
219                         goto printString;
220                 }
221                 
222                 // - Padding Side Flag
223                 if(c == '+') {
224                         bPadLeft = 1;
225                         c = *__format++;
226                 }
227                 
228                 // - Padding
229                 if(c == '0') {
230                         pad = '0';
231                         c = *__format++;
232                 }
233                 else
234                         pad = ' ';
235                 
236                 // - Minimum length
237                 if(c == '*') {  // Dynamic length
238                         minSize = va_arg(args, unsigned int);
239                         c = *__format++;
240                 }
241                 else if('1' <= c && c <= '9')
242                 {
243                         minSize = 0;
244                         while('0' <= c && c <= '9')
245                         {
246                                 minSize *= 10;
247                                 minSize += c - '0';
248                                 c = *__format++;
249                         }
250                 }
251                 else
252                         minSize = 1;
253                 
254                 // - Default, Long or LongLong?
255                 isLongLong = 0;
256                 if(c == 'l')    // Long is actually the default on x86
257                 {
258                         c = *__format++;
259                         if(c == 'l') {
260                                 c = *__format++;
261                                 isLongLong = 1;
262                         }
263                 }
264                 
265                 // - Now get the format code
266                 p = tmpBuf;
267                 switch(c)
268                 {
269                 case 'd':
270                 case 'i':
271                         GETVAL();
272                         if( isLongLong && val >> 63 ) {
273                                 PUTCH('-');
274                                 val = -val;
275                         }
276                         else if( !isLongLong && val >> 31 ) {
277                                 PUTCH('-');
278                                 val = -(Sint32)val;
279                         }
280                         itoa(p, val, 10, minSize, pad);
281                         goto printString;
282                 case 'u':
283                         GETVAL();
284                         itoa(p, val, 10, minSize, pad);
285                         goto printString;
286                 case 'X':
287                         #if BITS == 64
288                         isLongLong = 1; // TODO: Handle non-x86 64-bit archs
289                         #endif
290                         GETVAL();
291                         itoa(p, val, 16, minSize, pad);
292                         goto printString;
293                         
294                 case 'x':
295                         GETVAL();
296                         itoa(p, val, 16, minSize, pad);
297                         goto printString;
298                 case 'o':
299                         GETVAL();
300                         itoa(p, val, 8, minSize, pad);
301                         goto printString;
302                 case 'b':
303                         GETVAL();
304                         itoa(p, val, 2, minSize, pad);
305                         goto printString;
306
307                 case 'B':       //Boolean
308                         val = va_arg(args, unsigned int);
309                         if(val) p = "True";
310                         else    p = "False";
311                         goto printString;
312                 
313                 // String - Null Terminated Array
314                 case 's':
315                         p = va_arg(args, char*);        // Get Argument
316                 printString:
317                         if(!p)          p = "(null)";
318                         len = strlen(p);
319                         if( !bPadLeft ) while(len++ < minSize)  PUTCH(pad);
320                         while(*p)       PUTCH(*p++);
321                         if( bPadLeft )  while(len++ < minSize)  PUTCH(pad);
322                         break;
323                 
324                 case 'C':       // Non-Null Terminated Character Array
325                         p = va_arg(args, char*);
326                         if(!p)  goto printString;
327                         while(minSize--)        PUTCH(*p++);
328                         break;
329                 
330                 // Single Character
331                 case 'c':
332                 default:
333                         GETVAL();
334                         PUTCH( (Uint8)val );
335                         break;
336                 }
337         }
338         
339         if(__s && pos != __maxlen)
340                 __s[pos] = '\0';
341         
342         return pos;
343 }
344 #undef PUTCH
345
346 /**
347  */
348 int sprintf(char *__s, const char *__format, ...)
349 {
350         va_list args;
351          int    ret;
352         
353         va_start(args, __format);
354         ret = vsnprintf(__s, -1, __format, args);
355         va_end(args);
356         
357         return ret;
358 }
359
360 /**
361  * \fn int tolower(int c)
362  * \brief Converts a character to lower case
363  */
364 int tolower(int c)
365 {
366         if('A' <= c && c <= 'Z')
367                 return c - 'A' + 'a';
368         return c;
369 }
370
371 /**
372  * \fn int strucmp(const char *Str1, const char *Str2)
373  * \brief Compare \a Str1 and \a Str2 case-insensitively
374  */
375 int strucmp(const char *Str1, const char *Str2)
376 {
377         while(*Str1 && tolower(*Str1) == tolower(*Str2))
378                 Str1++, Str2++;
379         return tolower(*Str1) - tolower(*Str2);
380 }
381
382 /**
383  * \fn int strpos(const char *Str, char Ch)
384  * \brief Search a string for an ascii character
385  */
386 int strpos(const char *Str, char Ch)
387 {
388          int    pos;
389         for(pos=0;Str[pos];pos++)
390         {
391                 if(Str[pos] == Ch)      return pos;
392         }
393         return -1;
394 }
395
396 /**
397  * \fn Uint8 ByteSum(void *Ptr, int Size)
398  * \brief Adds the bytes in a memory region and returns the sum
399  */
400 Uint8 ByteSum(void *Ptr, int Size)
401 {
402         Uint8   sum = 0;
403         while(Size--)   sum += *(Uint8*)Ptr++;
404         return sum;
405 }
406
407 /**
408  * \fn Uint strlen(const char *__str)
409  * \brief Get the length of string
410  */
411 Uint strlen(const char *__str)
412 {
413         Uint    ret = 0;
414         while(*__str++) ret++;
415         return ret;
416 }
417
418 /**
419  * \fn char *strcpy(char *__str1, const char *__str2)
420  * \brief Copy a string to a new location
421  */
422 char *strcpy(char *__str1, const char *__str2)
423 {
424         while(*__str2)
425                 *__str1++ = *__str2++;
426         *__str1 = '\0'; // Terminate String
427         return __str1;
428 }
429
430 /**
431  * \fn char *strncpy(char *__str1, const char *__str2, size_t max)
432  * \brief Copy a string to a new location
433  */
434 char *strncpy(char *__str1, const char *__str2, size_t max)
435 {
436         while(*__str2 && max-- >= 1)
437                 *__str1++ = *__str2++;
438         if(max)
439                 *__str1 = '\0'; // Terminate String
440         return __str1;
441 }
442
443 /**
444  * \fn int strcmp(const char *str1, const char *str2)
445  * \brief Compare two strings return the difference between
446  *        the first non-matching characters.
447  */
448 int strcmp(const char *str1, const char *str2)
449 {
450         while(*str1 && *str1 == *str2)
451                 str1++, str2++;
452         return *str1 - *str2;
453 }
454
455 /**
456  * \fn int strncmp(const char *Str1, const char *Str2, size_t num)
457  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
458  */
459 int strncmp(const char *Str1, const char *Str2, size_t num)
460 {
461         if(num == 0)    return 0;       // TODO: Check what should officially happen here
462         while(--num && *Str1 && *Str1 == *Str2)
463                 Str1++, Str2++;
464         return *Str1-*Str2;
465 }
466
467 #if 0
468 /**
469  * \fn char *strdup(const char *Str)
470  * \brief Duplicates a string
471  */
472 char *strdup(const char *Str)
473 {
474         char    *ret;
475         ret = malloc(strlen(Str)+1);
476         if( !ret )      return NULL;
477         strcpy(ret, Str);
478         return ret;
479 }
480 #else
481
482 /**
483  * \fn char *_strdup(const char *File, int Line, const char *Str)
484  * \brief Duplicates a string
485  */
486 char *_strdup(const char *File, int Line, const char *Str)
487 {
488         char    *ret;
489         ret = Heap_Allocate(File, Line, strlen(Str)+1);
490         if( !ret )      return NULL;
491         strcpy(ret, Str);
492         return ret;
493 }
494 #endif
495
496 /**
497  * \brief Split a string using the passed character
498  * \return NULL terminated array of strings on the heap
499  * \param __str String to split
500  * \param __ch  Character to split by
501  */
502 char **str_split(const char *__str, char __ch)
503 {
504          int    i, j;
505          int    len = 1;
506         char    **ret;
507         char    *start;
508         
509         for( i = 0; __str[i]; i++ )
510         {
511                 if(__str[i] == __ch)
512                         len ++;
513         }
514         
515         ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
516         if( !ret )      return NULL;
517         
518         j = 1;
519         start = (char *)&ret[len+1];
520         ret[0] = start;
521         for( i = 0; __str[i]; i++ )
522         {
523                 if(__str[i] == __ch) {
524                         *start++ = '\0';
525                         ret[j++] = start;
526                 }
527                 else {
528                         *start++ = __str[i]; 
529                 }
530         }
531         *start = '\0';
532         ret[j] = NULL;
533         
534         return ret;
535 }
536
537 /**
538  * \fn int DivUp(int num, int dem)
539  * \brief Divide two numbers, rounding up
540  * \param num   Numerator
541  * \param dem   Denominator
542  */
543 int DivUp(int num, int dem)
544 {
545         return (num+dem-1)/dem;
546 }
547
548 /**
549  * \fn int strpos8(const char *str, Uint32 search)
550  * \brief Search a string for a UTF-8 character
551  */
552 int strpos8(const char *str, Uint32 Search)
553 {
554          int    pos;
555         Uint32  val = 0;
556         for(pos=0;str[pos];pos++)
557         {
558                 // ASCII Range
559                 if(Search < 128) {
560                         if(str[pos] == Search)  return pos;
561                         continue;
562                 }
563                 if(*(Uint8*)(str+pos) < 128)    continue;
564                 
565                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
566                 if(val == Search)       return pos;
567         }
568         return -1;
569 }
570
571 /**
572  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
573  * \brief Read a UTF-8 character from a string
574  */
575 int ReadUTF8(Uint8 *str, Uint32 *Val)
576 {
577         *Val = 0xFFFD;  // Assume invalid character
578         
579         // ASCII
580         if( !(*str & 0x80) ) {
581                 *Val = *str;
582                 return 1;
583         }
584         
585         // Middle of a sequence
586         if( (*str & 0xC0) == 0x80 ) {
587                 return 1;
588         }
589         
590         // Two Byte
591         if( (*str & 0xE0) == 0xC0 ) {
592                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
593                 str ++;
594                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
595                 *Val |= (*str & 0x3F);  // Lower 6 Bits
596                 return 2;
597         }
598         
599         // Three Byte
600         if( (*str & 0xF0) == 0xE0 ) {
601                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
602                 str ++;
603                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
604                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
605                 str ++;
606                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
607                 *Val |= (*str & 0x3F);  // Lower 6 Bits
608                 return 3;
609         }
610         
611         // Four Byte
612         if( (*str & 0xF1) == 0xF0 ) {
613                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
614                 str ++;
615                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
616                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
617                 str ++;
618                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
619                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
620                 str ++;
621                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
622                 *Val |= (*str & 0x3F);  // Lower 6 Bits
623                 return 4;
624         }
625         
626         // UTF-8 Doesn't support more than four bytes
627         return 4;
628 }
629
630 /**
631  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
632  * \brief Write a UTF-8 character sequence to a string
633  */
634 int WriteUTF8(Uint8 *str, Uint32 Val)
635 {
636         // ASCII
637         if( Val < 128 ) {
638                 *str = Val;
639                 return 1;
640         }
641         
642         // Two Byte
643         if( Val < 0x8000 ) {
644                 *str = 0xC0 | (Val >> 6);
645                 str ++;
646                 *str = 0x80 | (Val & 0x3F);
647                 return 2;
648         }
649         
650         // Three Byte
651         if( Val < 0x10000 ) {
652                 *str = 0xE0 | (Val >> 12);
653                 str ++;
654                 *str = 0x80 | ((Val >> 6) & 0x3F);
655                 str ++;
656                 *str = 0x80 | (Val & 0x3F);
657                 return 3;
658         }
659         
660         // Four Byte
661         if( Val < 0x110000 ) {
662                 *str = 0xF0 | (Val >> 18);
663                 str ++;
664                 *str = 0x80 | ((Val >> 12) & 0x3F);
665                 str ++;
666                 *str = 0x80 | ((Val >> 6) & 0x3F);
667                 str ++;
668                 *str = 0x80 | (Val & 0x3F);
669                 return 4;
670         }
671         
672         // UTF-8 Doesn't support more than four bytes
673         return 0;
674 }
675
676 /**
677  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
678  * \brief Converts a date into an Acess Timestamp
679  */
680 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
681 {
682         Sint64  stamp;
683         stamp = sec;
684         stamp += mins*60;
685         stamp += hrs*3600;
686         
687         stamp += day*3600*24;
688         stamp += month*DAYS_BEFORE[month]*3600*24;
689         if(     (
690                 ((year&3) == 0 || year%100 != 0)
691                 || (year%100 == 0 && ((year/100)&3) == 0)
692                 ) && month > 1) // Leap year and after feb
693                 stamp += 3600*24;
694         
695         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Four Year Segments
696         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
697         stamp += UNIX_TO_2K;
698         
699         return stamp * 1000;
700 }
701
702 /**
703  * \fn Uint rand()
704  * \brief Pseudo random number generator
705  * \note Unknown effectiveness (made up on the spot)
706  */
707 Uint rand(void)
708 {
709         #if 0
710         static Uint     state = RANDOM_SEED;
711         Uint    old = state;
712         // Get the next state value
713         giRandomState = (RANDOM_A*state + RANDOM_C);
714         // Check if it has changed, and if it hasn't, change it
715         if(state == old)        state += RANDOM_SPRUCE;
716         return state;
717         #else
718         // http://en.wikipedia.org/wiki/Xorshift
719         // 2010-10-03
720         static Uint32   x = 123456789;
721         static Uint32   y = 362436069;
722         static Uint32   z = 521288629;
723         static Uint32   w = 88675123; 
724         Uint32  t;
725  
726         t = x ^ (x << 11);
727         x = y; y = z; z = w;
728         return w = w ^ (w >> 19) ^ t ^ (t >> 8); 
729         #endif
730 }
731
732 /* *
733  * \name Memory Validation
734  * \{
735  */
736 /**
737  * \brief Checks if a string resides fully in valid memory
738  */
739 int CheckString(char *String)
740 {
741         if( !MM_GetPhysAddr( (tVAddr)String ) )
742                 return 0;
743         
744         // Check 1st page
745         if( MM_IsUser( (tVAddr)String ) )
746         {
747                 // Traverse String
748                 while( *String )
749                 {
750                         if( !MM_IsUser( (tVAddr)String ) )
751                                 return 0;
752                         // Increment string pointer
753                         String ++;
754                 }
755                 return 1;
756         }
757         else if( MM_GetPhysAddr( (tVAddr)String ) )
758         {
759                 // Traverse String
760                 while( *String )
761                 {
762                         if( !MM_GetPhysAddr( (tVAddr)String ) )
763                                 return 0;
764                         // Increment string pointer
765                         String ++;
766                 }
767                 return 1;
768         }
769         return 0;
770 }
771
772 /**
773  * \brief Check if a sized memory region is valid memory
774  */
775 int CheckMem(void *Mem, int NumBytes)
776 {
777         tVAddr  addr = (tVAddr)Mem;
778         
779         if( MM_IsUser( addr ) )
780         {
781                 while( NumBytes-- )
782                 {
783                         if( !MM_IsUser( addr ) )
784                                 return 0;
785                         addr ++;
786                 }
787                 return 1;
788         }
789         else if( MM_GetPhysAddr( addr ) )
790         {
791                 while( NumBytes-- )
792                 {
793                         if( !MM_GetPhysAddr( addr ) )
794                                 return 0;
795                         addr ++;
796                 }
797                 return 1;
798         }
799         return 0;
800 }
801 /* *
802  * \}
803  */
804
805 /**
806  * \brief Search a string array for \a Needle
807  * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
808  */
809 int ModUtil_LookupString(char **Array, char *Needle)
810 {
811          int    i;
812         if( !CheckString(Needle) )      return -1;
813         for( i = 0; Array[i]; i++ )
814         {
815                 if(strcmp(Array[i], Needle) == 0)       return i;
816         }
817         return -1;
818 }
819
820 int ModUtil_SetIdent(char *Dest, char *Value)
821 {
822         if( !CheckMem(Dest, 32) )       return -1;
823         strncpy(Dest, Value, 32);
824         return 1;
825 }

UCC git Repository :: git.ucc.asn.au