add more helper functions to deal with C string (strstr, strtol, strtoul, ...)

This commit is contained in:
Stefan Lankes 2014-12-29 00:11:04 +01:00
parent 187140ae99
commit 719b54b05a
8 changed files with 484 additions and 8 deletions

129
include/eduos/ctype.h Normal file
View file

@ -0,0 +1,129 @@
/****************************************************************************************
*
* Author: Stefan Lankes
* Chair for Operating Systems, RWTH Aachen University
* Date: 24/03/2011
*
****************************************************************************************
*
* Written by the Chair for Operating Systems, RWTH Aachen University
*
* NO Copyright (C) 2010, Stefan Lankes,
* consider these trivial functions to be public domain.
*
* These functions are distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/
/**
* @author Stefan Lankes
* @file include/eduos/ctype.h
* @brief Functions related to alphanumerical character values
*
* This file contains functions helping to determine
* the type of alphanumerical character values.
*/
#ifndef __CTYPE_H_
#define __CYTPE_H_
/** Returns true if the value of 'c' is an ASCII-charater */
static inline int isascii(int c)
{
return (((unsigned char)(c))<=0x7f);
}
/** Applies an and-operation to
* push the value of 'c' into the ASCII-range */
static inline int toascii(int c)
{
return (((unsigned char)(c))&0x7f);
}
/** Returns true if the value of 'c' is the
* space character or a control character */
static inline int isspace(int c)
{
if (!isascii(c))
return 0;
if (' ' == (unsigned char) c)
return 1;
if ('\n' == (unsigned char) c)
return 1;
if ('\r' == (unsigned char) c)
return 1;
if ('\t' == (unsigned char) c)
return 1;
if ('\v' == (unsigned char) c)
return 1;
if ('\f' == (unsigned char) c)
return 1;
return 0;
}
/** Returns true if the value of 'c' is a number */
static inline int isdigit(int c)
{
if (!isascii(c))
return 0;
if (((unsigned char) c >= '0') && ((unsigned char) c <= '9'))
return 1;
return 0;
}
/** Returns true if the value of 'c' is a lower case letter */
static inline int islower(int c)
{
if (!isascii(c))
return 0;
if (((unsigned char) c >= 'a') && ((unsigned char) c <= 'z'))
return 1;
return 0;
}
/** Returns true if the value of 'c' is an upper case letter */
static inline int isupper(int c)
{
if (!isascii(c))
return 0;
if (((unsigned char) c >= 'A') && ((unsigned char) c <= 'Z'))
return 1;
return 0;
}
/** Returns true if the value of 'c' is an alphabetic character */
static inline int isalpha(int c)
{
if (isupper(c) || islower(c))
return 1;
return 0;
}
/** Makes the input character lower case.\n Will do nothing if it
* was something different than an upper case letter before. */
static inline unsigned char tolower(unsigned char c)
{
if (isupper(c))
c -= 'A'-'a';
return c;
}
/** Makes the input character upper case.\n Will do nothing if it
* was something different than a lower case letter before. */
static inline unsigned char toupper(unsigned char c)
{
if (islower(c))
c -= 'a'-'A';
return c;
}
#endif

View file

@ -38,7 +38,7 @@
#define __STDLIB_H__
#include <eduos/config.h>
#include <asm/stddef.h>
#include <eduos/stddef.h>
#ifdef __cplusplus
extern "C" {
@ -50,6 +50,29 @@ extern "C" {
*/
void* create_stack(tid_t id);
/** @brief String to long
*
* @return Long value of the parsed numerical string
*/
long strtol(const char* str, char** endptr, int base);
/** @brief String to unsigned long
*
* @return Unsigned long value of the parsed numerical string
*/
unsigned long strtoul(const char* nptr, char** endptr, int base);
/** @brief ASCII to integer
*
* Convenience function using strtol().
*
* @return Integer value of the parsed numerical string
*/
static inline int atoi(const char *str)
{
return (int)strtol(str, (char **)NULL, 10);
}
#ifdef __cplusplus
}
#endif

View file

@ -54,11 +54,11 @@ size_t strlen(const char *str);
#endif
#ifndef HAVE_ARCH_STRNCPY
char* strncpy(char *dest, const char *src, size_t n);
char *strncpy(char *dest, const char *src, size_t n);
#endif
#ifndef HAVE_ARCH_STRCPY
char* strcpy(char *dest, const char *src);
char *strcpy(char *dest, const char *src);
#endif
#ifndef HAVE_ARCH_STRCMP
@ -69,6 +69,8 @@ int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
#endif
char *strstr(const char *s, const char *find);
#ifdef __cplusplus
}
#endif

View file

@ -1,4 +1,4 @@
C_source := string.c stdio.c printf.c sprintf.c moddi3.c umoddi3.c divdi3.c udivdi3.c qdivrem.c
C_source := string.c stdio.c printf.c sprintf.c strtol.c strtoul.c strstr.c moddi3.c umoddi3.c divdi3.c udivdi3.c qdivrem.c
MODULE := libkern
include $(TOPDIR)/Makefile.inc

View file

@ -31,6 +31,7 @@
#include <eduos/spinlock.h>
#include <asm/atomic.h>
#include <asm/processor.h>
#include <asm/multiboot.h>
#ifdef CONFIG_VGA
#include <asm/vga.h>
#endif
@ -56,6 +57,11 @@ int koutput_init(void)
#ifdef CONFIG_VGA
vga_init();
#endif
#ifdef CONFIG_UART
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_CMDLINE))
if (!uart_early_init((char*) mb_info->cmdline))
early_print |= UART_EARLY_PRINT;
#endif
return 0;
}
@ -114,12 +120,14 @@ int kputs(const char *str)
int koutput_add_uart(void)
{
#ifdef CONFIG_UART
uint32_t i;
if (!(early_print & UART_EARLY_PRINT)) {
uint32_t i;
early_print |= UART_EARLY_PRINT;
early_print |= UART_EARLY_PRINT;
for(i=0; i<atomic_int32_read(&kmsg_counter); i++)
uart_putchar(kmessages[i % KMSG_SIZE]);
for(i=0; i<atomic_int32_read(&kmsg_counter); i++)
uart_putchar(kmessages[i % KMSG_SIZE]);
}
return 0;
#else

69
libkern/strstr.c Normal file
View file

@ -0,0 +1,69 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* The code has been taken from FreeBSD (sys/libkern/strstr.c) and is therefore
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
* have been added.
*/
/* eduOS prelude */
#include <eduos/stdlib.h>
#include <eduos/string.h>
#include <eduos/ctype.h>
#include <asm/limits.h>
/*
* Find the first occurrence of find in s.
*/
char *
strstr(const char *s, const char *find)
{
char c, sc;
size_t len;
if ((c = *find++) != 0) {
len = strlen(find);
do {
do {
if ((sc = *s++) == 0)
return (NULL);
} while (sc != c);
} while (strncmp(s, find, len) != 0);
s--;
}
return ((char *) s);
}

133
libkern/strtol.c Normal file
View file

@ -0,0 +1,133 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From: @(#)strtol.c 8.1 (Berkeley) 6/4/93
*/
/*
* The code has been taken from FreeBSD (sys/libkern/strtol.c) and is therefore
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
* have been added.
*/
/* eduOS prelude */
#include <eduos/stddef.h>
#include <eduos/ctype.h>
#include <asm/limits.h>
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
strtol(nptr, endptr, base)
const char *nptr;
char **endptr;
int base;
{
const char *s = nptr;
unsigned long acc;
unsigned char c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (!isascii(c))
break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
} else if (neg)
acc = -acc;
if (endptr != 0)
*((const char **)endptr) = any ? s - 1 : nptr;
return (acc);
}

112
libkern/strtoul.c Normal file
View file

@ -0,0 +1,112 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From: @(#)strtoul.c 8.1 (Berkeley) 6/4/93
*/
/*
* The code has been taken from FreeBSD (sys/libkern/strtoul.c) and is therefore
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
* have been added.
*/
/* eduOS prelude */
#include <eduos/stddef.h>
#include <eduos/ctype.h>
#include <asm/limits.h>
/*
* Convert a string to an unsigned long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
unsigned long
strtoul(nptr, endptr, base)
const char *nptr;
char **endptr;
int base;
{
const char *s = nptr;
unsigned long acc;
unsigned char c;
unsigned long cutoff;
int neg = 0, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (!isascii(c))
break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
} else if (neg)
acc = -acc;
if (endptr != 0)
*((const char **)endptr) = any ? s - 1 : nptr;
return (acc);
}