Skip to content

Commit 1e27467

Browse files
authored
Merge pull request #4 from sandbox-science/Develop
Implemented strcmp() and strlen()
2 parents c8442e8 + 556cfe5 commit 1e27467

File tree

9 files changed

+213
-58
lines changed

9 files changed

+213
-58
lines changed

doc/AstraKernelManual.pdf

6.25 KB
Binary file not shown.

doc/contents/datetime.tex

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
\section{Timekeeping API}
33
Provide calendar dates and clock time based on the on-chip RTC.
44

5-
\subsection*{Overview}
5+
\paragraph{Overview}
66
\begin{itemize}
77
\item Reads a 32-bit seconds-since-1970 counter (RTC register at `0x101e8000`).
88
\item Exposes two APIs:
@@ -35,30 +35,30 @@ \subsection*{Data Structure}
3535
Data Register(\textbf{RTCDR}). This is a 32 bit register, and therefore
3636
\underline{subject to the Year 2038 Problem}.
3737

38-
\subsection{API: \texttt{uint32\_t getdate(dateval *date\_struct)}}
38+
\subsection{\texttt{uint32\_t getdate(dateval *date\_struct)}}
3939
Populate the provided \texttt{*date\_struct} with the current date in days, months, and years.
4040

41-
\subsubsection*{Parameters}
41+
\paragraph{Parameters}
4242
\begin{itemize}
4343
\item \texttt{date\_struct} pointer to a \texttt{dateval} structure; if \texttt{NULL},
4444
only the raw \textbf{RTC} counter is returned.
4545
\end{itemize}
4646

47-
\subsubsection*{Return Value}
47+
\paragraph{Return Value}
4848
\begin{itemize}
4949
\item Returns number of seconds since epoch (\texttt{RTCDR}) as read from the hardware register.
5050
\end{itemize}
5151

52-
\subsection{API: \texttt{uint32\_t gettime(timeval *time\_struct)}}
52+
\subsection{\texttt{uint32\_t gettime(timeval *time\_struct)}}
5353
Populate \texttt{*time\_struct} with the current click time in hours, minutes, and seconds.
5454

55-
\subsubsection*{Parameters}
55+
\paragraph{Parameters}
5656
\begin{itemize}
5757
\item \texttt{time\_struct} pointer to a \texttt{timeval} structure; if \texttt{NULL},
5858
only the raw \textbf{RTC} counter is returned.
5959
\end{itemize}
6060

61-
\subsubsection*{Return Value}
61+
\paragraph{Return Value}
6262
\begin{itemize}
6363
\item Returns number of seconds since epoch (\texttt{RTCDR}) as read from the hardware register.
6464
\end{itemize}

doc/contents/puts.tex renamed to doc/contents/print.tex

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,45 @@
11
% ------------------------------------------------
2-
% *** Section 2: I/O API ***
2+
% *** Section 2: I/O \& Time Services ***
33
% ------------------------------------------------
44
\newpage
55
\chapter{I/O \& Time Services}
66

7-
\section{UART Device Driver}
7+
\section{UART Output API}
8+
89
\subsubsection{Registers \& Constants}
910
\begin{itemize}
1011
\item \textbf{UART0\_DR} (Data Register), \texttt{0x101f1000}
1112
\item \textbf{UART0\_FR} (Flag Register), \texttt{0x101f1018}
1213
\item \textbf{UART\_FR\_TXFF}, \textbf{UART\_FR\_RXFE}
1314
\end{itemize}
1415

15-
\subsection{API: \texttt{printf(char *s, ...)}}
16+
\subsection{\texttt{printf(char *s, ...)}}
17+
18+
\paragraph{Description}
1619
Sends a null-terminated format string over UART. If an incorrect datatype is given
1720
for a format specifier, \underline{the behavior is undefined}. If a format specifier
1821
is given without a matching argument, it is simply skipped when the string is outputted.
1922
The following format specifiers are supported:
2023

24+
\paragraph{Supported Format Specifiers}
2125
\begin{itemize}
22-
\item \textbf{\%c}: Expects a single character.
23-
\item \textbf{\%s}: Expects a null-terminated string.
24-
\item \textbf{\%d}: For 32-bit signed integers in the range \texttt{-2147483648} to \texttt{2147483647}.
25-
\item \textbf{\%ld}: For 64-bit signed integers in the range \texttt{-9223372036854775808} to \texttt{9223372036854775807}, excluding the range specified above, for \textbf{\%d}.
26-
\item \textbf{\%lu}: For 64-bit unsigned integers in the range \texttt{2147483648} to \texttt{18446744073709551615}.
27-
\item \textbf{\%x} and \textbf{\%X}: For 32-bit unsigned integers in the range \texttt{0} to \texttt{2147483647}, where the case of \texttt{x} determines the case of the hexadecimal digits (\texttt{a-f} or \texttt{A-F}).
28-
\item \textbf{\%lx} and \textbf{\%lX}: For 64-bit unsigned integers printed in hexadecimal format. Has the same range as \textbf{\%lu}. The case of \texttt{x} determines the case of the hexadecimal digits (\texttt{a-f} or \texttt{A-F}).
29-
\item \textbf{\%\%}: Outputs a '\%'.
30-
\item \textbf{\%}: Outputs (null). This is a special case where the format specifier is not followed by any character, and it simply outputs nothing.
26+
\item \texttt{\%c}: Expects a single character.
27+
\item \texttt{\%s}: Expects a null-terminated string.
28+
\item \texttt{\%d}: For 32-bit signed integers in the range \texttt{-2147483648} to \texttt{2147483647}.
29+
\item \texttt{\%ld}: For 64-bit signed integers in the range \texttt{-9223372036854775808} to \texttt{9223372036854775807}, excluding the range specified above, for \textbf{\%d}.
30+
\item \texttt{\%lu}: For 64-bit unsigned integers in the range \texttt{2147483648} to \texttt{18446744073709551615}.
31+
\item \texttt{\%x}, \texttt{\%X}: For 32-bit unsigned integers in the range \texttt{0} to \texttt{2147483647}, where the case of \texttt{x} determines the case of the hexadecimal digits (\texttt{a-f} or \texttt{A-F}).
32+
\item \texttt{\%lx}, \texttt{\%lX}: For 64-bit unsigned integers printed in hexadecimal format. Has the same range as \textbf{\%lu}. The case of \texttt{x} determines the case of the hexadecimal digits (\texttt{a-f} or \texttt{A-F}).
33+
\item \texttt{\%\%}: Outputs a literal \texttt{\%}.
34+
\item \texttt{\%}: If the format specifier is not followed by a valid character, prints \texttt{(null)}.
3135
\end{itemize}
3236

3337
\begin{flushleft}
3438
All the ranges specified above are inclusive. Also, note that integers in the
3539
range \texttt{-2147483648} to \texttt{2147483647} are passed as 32 bit integers
3640
and any integers not part of this range are passed as 64 bit integers \underline{by default}.
3741
If desired, integers of this range can be cast as \texttt{long long} or \texttt{unsigned long long}
38-
for use with the format specifiers prefixed by \textbf{l}(ell).
42+
for use with the format specifiers prefixed by the character \texttt{l}.
3943
\end{flushleft}
4044

4145
\subsection*{Examples}

doc/contents/string.tex

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
\newpage
2+
\section{String Manipulation API}
3+
\subsection{\texttt{strcmp(const char *str\_1, const char *str\_2)}}
4+
5+
\paragraph{Purpose}
6+
Compares two null-terminated strings, character by character.
7+
8+
\paragraph{Overview}
9+
This function compares the characters of two strings (\texttt{ASCII values}),
10+
\texttt{str\_1} and \texttt{str\_2}, one by one. It returns:
11+
12+
\paragraph{Return Values}
13+
\begin{itemize}
14+
\item 0 if both strings are equal,
15+
\item -1 if the first differing character in \texttt{str\_1} is less than that in \texttt{str\_2},
16+
\item 1 if the first differing character in \texttt{str\_1} is greater than that in \texttt{str\_2}.
17+
\end{itemize}
18+
19+
\paragraph{Behavior}
20+
The comparison stops at the first difference or the null terminator.
21+
Case sensitivity is observed. Behavior is undefined if either pointer is not a
22+
valid null-terminated string.
23+
24+
\subsection*{Examples}
25+
\begin{lstlisting}[language=C, caption=String Comparison Example]
26+
int result = strcmp("abc", "abc"); // Expect 0
27+
printf("Expect 0 -> %d\n", result);
28+
29+
result = strcmp("abc", "abd"); // Expect -1
30+
printf("Expect -1 -> %d\n", result);
31+
32+
result = strcmp("abc", "ABC"); // Expect 1
33+
printf("Expect 1 -> %d\n", result);
34+
\end{lstlisting}
35+
36+
\begin{note}
37+
In the future, we could returning the difference between the first differing
38+
characters, which would allow for more detailed comparisons. This would enable
39+
users to understand how far apart the strings are in terms of character values.
40+
\end{note}
41+
42+
\subsection{\texttt{strlen(const char *str)}}
43+
44+
\paragraph{Purpose}
45+
Calculates the length of a null-terminated string.
46+
47+
\paragraph{Overview}
48+
This function counts the number of characters in a null-terminated string,
49+
excluding the null terminator itself. It returns the length of the string as an
50+
unsigned integer. This function uses pointer arithmetic to traverse the string,
51+
performing mathematical operations directly on the pointer values.
52+
53+
\paragraph{Return Values}
54+
\begin{itemize}
55+
\item The number of characters in the string, not including the null terminator.
56+
\item 0 if the string is empty (i.e., the first character is the null terminator).
57+
\end{itemize}
58+
59+
\paragraph{Behavior}
60+
The function iterates through the input string until the null terminator is found, returning
61+
the number of characters preceding it. If the input pointer is not a valid
62+
null-terminated string, the behavior is undefined.
63+
64+
\subsection*{Examples}
65+
\begin{lstlisting}[language=C, caption=String Length Example]
66+
size_t result = strlen("abc"); // Expect 3
67+
printf("Expect len 3 -> %d\n", result);
68+
69+
result = strlen(""); // Expect 0
70+
printf("Expect len 0 -> %d\n", result);
71+
\end{lstlisting}

doc/front/preface.tex

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ \section*{Preface}
4141

4242
\addcontentsline{toc}{section}{About This Project}
4343
\section*{About This Project}
44-
\subsection*{Resources}
44+
\paragraph{Resources}
4545

4646
To guide my learning and support development of AstraKernel, I am using the following resources,
4747
which are particularly valuable for foundational and practical understanding of OS design:
@@ -50,26 +50,28 @@ \subsection*{Resources}
5050
\item \textbf{The Little Book About OS Development} by Erik Helin and Adam Renberg
5151
\end{itemize}
5252

53-
\subsection*{Acknowledgments \& Contributions}
53+
\paragraph{Contributions}
5454

5555
AstraKernel is an open source project, and I encourage contributions from anyone
5656
interested in improving, extending the kernel or simply experiment with it. I also
5757
encourage anyone to improve this documentation, as it is a work in progress.
5858
If you would like to contribute, please feel free to open an issue or pull request on the GitHub repository.
59+
\\
5960
\begin{info}
6061
You can join the Matrix Server \url{https://matrix.to/#/#sandboxscience:matrix.org}
6162
for general SandBox Science discussion as well as project-specific discussion such
6263
as AstraKernel development.
6364
\end{info}
6465

65-
\noindent
66+
\paragraph{Acknowledgments}
6667
Specially thanks to the following individuals for their contributions:
6768
\begin{itemize}
68-
\item \textbf{shade5144} (\url{https://github.com/shade5144}) for contributing the initial version of the \texttt{printf}
69-
function as well as the documentation for it.
69+
\item \textbf{shade5144} (\url{https://github.com/shade5144}) for contributing
70+
the initial version of the \texttt{printf} and \texttt{datetime} function as
71+
well as the documentation for them.
7072
\end{itemize}
7173

72-
\subsection*{Disclaimer}
74+
\paragraph{Disclaimer}
7375

7476
AstraKernel is currently in its early stages of development and is not intended for production use.
7577
It is primarily an educational and experimental project. The code is provided as-is,

doc/main.tex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
% % *** Main Content ***
1919
% % -----------------------------------------------------
2020
\input{contents/introduction}
21-
\input{contents/puts}
21+
\input{contents/print}
22+
\input{contents/string}
2223
\input{contents/datetime}
2324

2425
\end{document}

include/string.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef STRING_H
2+
#define STRING_H
3+
4+
#include <stddef.h>
5+
6+
#ifdef __cplusplus
7+
extern "C"
8+
{
9+
#endif
10+
11+
int strcmp(const char *str_1, const char *str_2);
12+
size_t strlen(const char *str);
13+
14+
#ifdef __cplusplus
15+
}
16+
#endif
17+
18+
#endif // STRING_H

kernel/kernel.c

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "datetime.h"
55
#include "printf.h"
66
#include "clear.h"
7+
#include "string.h"
78

89
static const char *banner[] = {
910
"========================================\r\n",
@@ -53,37 +54,50 @@ void kernel_main(void)
5354

5455
switch (input_buffer[0])
5556
{
56-
case 'h': // Check for help command
57-
printf("\nHelp:\n 'q' to exit\n 'h' for help\n 'c' to clear screen\n 't' to print current time\n 'd' to print current date\r\n");
58-
break;
59-
case 'e': // TODO: This is for testing purposes. Remove once not needed
60-
printf("%ld %ld %ld\n", 0, -9223372036854775808, 9223372036854775807);
61-
printf("%d %d\n", 2147483647, -2147483648);
62-
printf("%x %lx %lX %X\n", 2147483647, 2147483649, 2147483648, 1234);
63-
printf("%lX %x %lx\n", 0x123456789abcdef0, 1234, 9223372036854775809);
64-
printf("Name: %c\n", 'b');
65-
printf("Hello %s\n", "World");
66-
printf("100%%\n");
67-
break;
68-
case 'q': // Check for exit command
69-
printf("Exiting...\r\n");
70-
is_running = false;
71-
break;
72-
case 'c': // Check for clear screen command
73-
clear();
74-
break;
75-
76-
case 't': // Check for time command
77-
gettime(&time_struct);
78-
printf("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
79-
break;
80-
case 'd': // Check for date command
81-
getdate(&date_struct);
82-
printf("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
83-
break;
84-
default:
85-
printf("Unknown command. Type 'h' for help.\r\n");
86-
break;
57+
case 'h': // Check for help command
58+
printf("\nHelp:\n 'q' to exit\n 'h' for help\n 'c' to clear screen\n 't' to print current time\n 'd' to print current date\r\n");
59+
break;
60+
case 'e':
61+
int result = strcmp("abc", "abc"); // Expect 0
62+
printf("Expect 0 -> %d\n", result);
63+
64+
result = strcmp("abc", "abd"); // Expect -1
65+
printf("Expect -1 -> %d\n", result);
66+
67+
result = strcmp("abc", "ABC"); // Expect 1
68+
printf("Expect 1 -> %d\n", result);
69+
70+
result = strcmp("ABC", "abc"); // Expect -1
71+
printf("Expect -1 -> %d\n", result);
72+
73+
result = strcmp("\x01\x02\x03", "\x01\x02\x03"); // Expect 0
74+
printf("Expect 0 -> %d\n", result);
75+
76+
result = strcmp("\x01\x02\x03", "\x01\x02\x04"); // Expect -1
77+
printf("Expect -1 -> %d\n", result);
78+
79+
result = strcmp("\x01\x02\x04", "\x01\x02\x03"); // Expect 1
80+
printf("Expect 1 -> %d\n", result);
81+
break;
82+
case 'q': // Check for exit command
83+
printf("Exiting...\r\n");
84+
is_running = false;
85+
break;
86+
case 'c': // Check for clear screen command
87+
clear();
88+
break;
89+
90+
case 't': // Check for time command
91+
gettime(&time_struct);
92+
printf("Current time(GMT): %d:%d:%d\n", time_struct.hrs, time_struct.mins, time_struct.secs);
93+
break;
94+
case 'd': // Check for date command
95+
getdate(&date_struct);
96+
printf("Current date(MM-DD-YYYY): %d-%d-%d\n", date_struct.month, date_struct.day, date_struct.year);
97+
break;
98+
default:
99+
printf("Unknown command. Type 'h' for help.\r\n");
100+
break;
87101
}
88102
}
89103
}

user/string.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "string.h"
2+
3+
/**
4+
* @brief Compares two null-terminated strings lexicographically.
5+
*
6+
* @param str_1 Pointer to the first string to compare.
7+
* @param str_2 Pointer to the second string to compare.
8+
*
9+
* @return int 0 if strings are equal, -1 if `str_1` < `str_2`, 1 if `str_1` > `str_2`.
10+
*/
11+
int strcmp(const char *str_1, const char *str_2)
12+
{
13+
unsigned char ch1, ch2;
14+
do
15+
{
16+
ch1 = *str_1++;
17+
ch2 = *str_2++;
18+
19+
if (ch1 != ch2)
20+
{
21+
// NOTE: If needed in the future, can return the difference between
22+
// the strings rather than just -1 or 1
23+
return ch1 < ch2 ? -1 : 1;
24+
}
25+
26+
} while (ch1);
27+
28+
return 0;
29+
}
30+
31+
/**
32+
* @brief Calculates the length of a null-terminated string.
33+
*
34+
* @param str Pointer to the null-terminated string to be measured.
35+
* @return The number of characters in the string, excluding the null terminator.
36+
*/
37+
size_t strlen(const char *str)
38+
{
39+
const char *s = str;
40+
while (*s)
41+
{
42+
++s;
43+
}
44+
return s - str;
45+
}

0 commit comments

Comments
 (0)