diff options
| author | manuel <manuel@mausz.at> | 2012-03-27 11:51:08 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-03-27 11:51:08 +0200 |
| commit | 4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b (patch) | |
| tree | 868c52e06f207b5ec8a3cc141f4b8b2bdfcc165c /examples | |
| parent | eae0bd57f0a26314a94785061888d193d186944a (diff) | |
| download | progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.gz progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.bz2 progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.zip | |
reorganize file structure to match the upstream requirements
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/.gitignore | 19 | ||||
| -rw-r--r-- | examples/Makefile | 36 | ||||
| -rw-r--r-- | examples/bubsort.c | 38 | ||||
| -rw-r--r-- | examples/cat.c | 34 | ||||
| -rw-r--r-- | examples/cmp.c | 68 | ||||
| -rw-r--r-- | examples/cp.c | 55 | ||||
| -rw-r--r-- | examples/echo.c | 14 | ||||
| -rw-r--r-- | examples/halt.c | 14 | ||||
| -rw-r--r-- | examples/hello.c | 9 | ||||
| -rw-r--r-- | examples/hex-dump.c | 35 | ||||
| -rw-r--r-- | examples/insult.c | 369 | ||||
| -rw-r--r-- | examples/lib/.gitignore | 1 | ||||
| -rw-r--r-- | examples/lib/user/.dummy | 0 | ||||
| -rw-r--r-- | examples/lib/user/.gitignore | 1 | ||||
| -rw-r--r-- | examples/lineup.c | 46 | ||||
| -rw-r--r-- | examples/ls.c | 90 | ||||
| -rw-r--r-- | examples/matmult.c | 57 | ||||
| -rw-r--r-- | examples/mcat.c | 45 | ||||
| -rw-r--r-- | examples/mcp.c | 68 | ||||
| -rw-r--r-- | examples/mkdir.c | 24 | ||||
| -rw-r--r-- | examples/pwd.c | 152 | ||||
| -rw-r--r-- | examples/recursor.c | 34 | ||||
| -rw-r--r-- | examples/rm.c | 21 | ||||
| -rw-r--r-- | examples/shell.c | 104 | ||||
| -rw-r--r-- | examples/test.c | 101 |
25 files changed, 1435 insertions, 0 deletions
diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..a9e09d7 --- /dev/null +++ b/examples/.gitignore | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | cat | ||
| 2 | cmp | ||
| 3 | cp | ||
| 4 | echo | ||
| 5 | halt | ||
| 6 | hex-dump | ||
| 7 | ls | ||
| 8 | mcat | ||
| 9 | mcp | ||
| 10 | mkdir | ||
| 11 | pwd | ||
| 12 | rm | ||
| 13 | shell | ||
| 14 | bubsort | ||
| 15 | insult | ||
| 16 | lineup | ||
| 17 | matmult | ||
| 18 | recursor | ||
| 19 | *.d | ||
diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 0000000..f773950 --- /dev/null +++ b/examples/Makefile | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | SRCDIR = .. | ||
| 2 | |||
| 3 | # Test programs to compile, and a list of sources for each. | ||
| 4 | # To add a new test, put its name on the PROGS list | ||
| 5 | # and then add a name_SRC line that lists its source files. | ||
| 6 | PROGS = cat cmp cp echo halt hello hex-dump ls mcat mcp mkdir pwd rm shell \ | ||
| 7 | bubsort insult lineup matmult recursor test | ||
| 8 | |||
| 9 | # Should work from project 2 onward. | ||
| 10 | cat_SRC = cat.c | ||
| 11 | cmp_SRC = cmp.c | ||
| 12 | cp_SRC = cp.c | ||
| 13 | echo_SRC = echo.c | ||
| 14 | halt_SRC = halt.c | ||
| 15 | hello_SRC = hello.c | ||
| 16 | hex-dump_SRC = hex-dump.c | ||
| 17 | insult_SRC = insult.c | ||
| 18 | lineup_SRC = lineup.c | ||
| 19 | ls_SRC = ls.c | ||
| 20 | recursor_SRC = recursor.c | ||
| 21 | rm_SRC = rm.c | ||
| 22 | test_SRC = test.c | ||
| 23 | |||
| 24 | # Should work in project 3; also in project 4 if VM is included. | ||
| 25 | bubsort_SRC = bubsort.c | ||
| 26 | matmult_SRC = matmult.c | ||
| 27 | mcat_SRC = mcat.c | ||
| 28 | mcp_SRC = mcp.c | ||
| 29 | |||
| 30 | # Should work in project 4. | ||
| 31 | mkdir_SRC = mkdir.c | ||
| 32 | pwd_SRC = pwd.c | ||
| 33 | shell_SRC = shell.c | ||
| 34 | |||
| 35 | include $(SRCDIR)/Make.config | ||
| 36 | include $(SRCDIR)/Makefile.userprog | ||
diff --git a/examples/bubsort.c b/examples/bubsort.c new file mode 100644 index 0000000..343219e --- /dev/null +++ b/examples/bubsort.c | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* sort.c | ||
| 2 | |||
| 3 | Test program to sort a large number of integers. | ||
| 4 | |||
| 5 | Intention is to stress virtual memory system. | ||
| 6 | |||
| 7 | Ideally, we could read the unsorted array off of the file | ||
| 8 | system, and store the result back to the file system! */ | ||
| 9 | #include <stdio.h> | ||
| 10 | |||
| 11 | /* Size of array to sort. */ | ||
| 12 | #define SORT_SIZE 128 | ||
| 13 | |||
| 14 | int | ||
| 15 | main (void) | ||
| 16 | { | ||
| 17 | /* Array to sort. Static to reduce stack usage. */ | ||
| 18 | static int array[SORT_SIZE]; | ||
| 19 | |||
| 20 | int i, j, tmp; | ||
| 21 | |||
| 22 | /* First initialize the array in descending order. */ | ||
| 23 | for (i = 0; i < SORT_SIZE; i++) | ||
| 24 | array[i] = SORT_SIZE - i - 1; | ||
| 25 | |||
| 26 | /* Then sort in ascending order. */ | ||
| 27 | for (i = 0; i < SORT_SIZE - 1; i++) | ||
| 28 | for (j = 0; j < SORT_SIZE - 1 - i; j++) | ||
| 29 | if (array[j] > array[j + 1]) | ||
| 30 | { | ||
| 31 | tmp = array[j]; | ||
| 32 | array[j] = array[j + 1]; | ||
| 33 | array[j + 1] = tmp; | ||
| 34 | } | ||
| 35 | |||
| 36 | printf ("sort exiting with code %d\n", array[0]); | ||
| 37 | return array[0]; | ||
| 38 | } | ||
diff --git a/examples/cat.c b/examples/cat.c new file mode 100644 index 0000000..c8d229d --- /dev/null +++ b/examples/cat.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* cat.c | ||
| 2 | |||
| 3 | Prints files specified on command line to the console. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | bool success = true; | ||
| 12 | int i; | ||
| 13 | |||
| 14 | for (i = 1; i < argc; i++) | ||
| 15 | { | ||
| 16 | int fd = open (argv[i]); | ||
| 17 | if (fd < 0) | ||
| 18 | { | ||
| 19 | printf ("%s: open failed\n", argv[i]); | ||
| 20 | success = false; | ||
| 21 | continue; | ||
| 22 | } | ||
| 23 | for (;;) | ||
| 24 | { | ||
| 25 | char buffer[1024]; | ||
| 26 | int bytes_read = read (fd, buffer, sizeof buffer); | ||
| 27 | if (bytes_read == 0) | ||
| 28 | break; | ||
| 29 | write (STDOUT_FILENO, buffer, bytes_read); | ||
| 30 | } | ||
| 31 | close (fd); | ||
| 32 | } | ||
| 33 | return success ? EXIT_SUCCESS : EXIT_FAILURE; | ||
| 34 | } | ||
diff --git a/examples/cmp.c b/examples/cmp.c new file mode 100644 index 0000000..94b406d --- /dev/null +++ b/examples/cmp.c | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* cat.c | ||
| 2 | |||
| 3 | Compares two files. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | int fd[2]; | ||
| 12 | |||
| 13 | if (argc != 3) | ||
| 14 | { | ||
| 15 | printf ("usage: cmp A B\n"); | ||
| 16 | return EXIT_FAILURE; | ||
| 17 | } | ||
| 18 | |||
| 19 | /* Open files. */ | ||
| 20 | fd[0] = open (argv[1]); | ||
| 21 | if (fd[0] < 0) | ||
| 22 | { | ||
| 23 | printf ("%s: open failed\n", argv[1]); | ||
| 24 | return EXIT_FAILURE; | ||
| 25 | } | ||
| 26 | fd[1] = open (argv[2]); | ||
| 27 | if (fd[1] < 0) | ||
| 28 | { | ||
| 29 | printf ("%s: open failed\n", argv[1]); | ||
| 30 | return EXIT_FAILURE; | ||
| 31 | } | ||
| 32 | |||
| 33 | /* Compare data. */ | ||
| 34 | for (;;) | ||
| 35 | { | ||
| 36 | int pos; | ||
| 37 | char buffer[2][1024]; | ||
| 38 | int bytes_read[2]; | ||
| 39 | int min_read; | ||
| 40 | int i; | ||
| 41 | |||
| 42 | pos = tell (fd[0]); | ||
| 43 | bytes_read[0] = read (fd[0], buffer[0], sizeof buffer[0]); | ||
| 44 | bytes_read[1] = read (fd[1], buffer[1], sizeof buffer[1]); | ||
| 45 | min_read = bytes_read[0] < bytes_read[1] ? bytes_read[0] : bytes_read[1]; | ||
| 46 | if (min_read == 0) | ||
| 47 | break; | ||
| 48 | |||
| 49 | for (i = 0; i < min_read; i++) | ||
| 50 | if (buffer[0][i] != buffer[1][i]) | ||
| 51 | { | ||
| 52 | printf ("Byte %d is %02hhx ('%c') in %s but %02hhx ('%c') in %s\n", | ||
| 53 | pos + i, | ||
| 54 | buffer[0][i], buffer[0][i], argv[1], | ||
| 55 | buffer[1][i], buffer[1][i], argv[2]); | ||
| 56 | return EXIT_FAILURE; | ||
| 57 | } | ||
| 58 | |||
| 59 | if (min_read < bytes_read[1]) | ||
| 60 | printf ("%s is shorter than %s\n", argv[1], argv[2]); | ||
| 61 | else if (min_read < bytes_read[0]) | ||
| 62 | printf ("%s is shorter than %s\n", argv[2], argv[1]); | ||
| 63 | } | ||
| 64 | |||
| 65 | printf ("%s and %s are identical\n", argv[1], argv[2]); | ||
| 66 | |||
| 67 | return EXIT_SUCCESS; | ||
| 68 | } | ||
diff --git a/examples/cp.c b/examples/cp.c new file mode 100644 index 0000000..86a5cd7 --- /dev/null +++ b/examples/cp.c | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* cat.c | ||
| 2 | |||
| 3 | Copies one file to another. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | int in_fd, out_fd; | ||
| 12 | |||
| 13 | if (argc != 3) | ||
| 14 | { | ||
| 15 | printf ("usage: cp OLD NEW\n"); | ||
| 16 | return EXIT_FAILURE; | ||
| 17 | } | ||
| 18 | |||
| 19 | /* Open input file. */ | ||
| 20 | in_fd = open (argv[1]); | ||
| 21 | if (in_fd < 0) | ||
| 22 | { | ||
| 23 | printf ("%s: open failed\n", argv[1]); | ||
| 24 | return EXIT_FAILURE; | ||
| 25 | } | ||
| 26 | |||
| 27 | /* Create and open output file. */ | ||
| 28 | if (!create (argv[2], filesize (in_fd))) | ||
| 29 | { | ||
| 30 | printf ("%s: create failed\n", argv[2]); | ||
| 31 | return EXIT_FAILURE; | ||
| 32 | } | ||
| 33 | out_fd = open (argv[2]); | ||
| 34 | if (out_fd < 0) | ||
| 35 | { | ||
| 36 | printf ("%s: open failed\n", argv[2]); | ||
| 37 | return EXIT_FAILURE; | ||
| 38 | } | ||
| 39 | |||
| 40 | /* Copy data. */ | ||
| 41 | for (;;) | ||
| 42 | { | ||
| 43 | char buffer[1024]; | ||
| 44 | int bytes_read = read (in_fd, buffer, sizeof buffer); | ||
| 45 | if (bytes_read == 0) | ||
| 46 | break; | ||
| 47 | if (write (out_fd, buffer, bytes_read) != bytes_read) | ||
| 48 | { | ||
| 49 | printf ("%s: write failed\n", argv[2]); | ||
| 50 | return EXIT_FAILURE; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | return EXIT_SUCCESS; | ||
| 55 | } | ||
diff --git a/examples/echo.c b/examples/echo.c new file mode 100644 index 0000000..1b136f2 --- /dev/null +++ b/examples/echo.c | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <syscall.h> | ||
| 3 | |||
| 4 | int | ||
| 5 | main (int argc, char **argv) | ||
| 6 | { | ||
| 7 | int i; | ||
| 8 | |||
| 9 | for (i = 0; i < argc; i++) | ||
| 10 | printf ("%s ", argv[i]); | ||
| 11 | printf ("\n"); | ||
| 12 | |||
| 13 | return EXIT_SUCCESS; | ||
| 14 | } | ||
diff --git a/examples/halt.c b/examples/halt.c new file mode 100644 index 0000000..bad7250 --- /dev/null +++ b/examples/halt.c | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | /* halt.c | ||
| 2 | |||
| 3 | Simple program to test whether running a user program works. | ||
| 4 | |||
| 5 | Just invokes a system call that shuts down the OS. */ | ||
| 6 | |||
| 7 | #include <syscall.h> | ||
| 8 | |||
| 9 | int | ||
| 10 | main (void) | ||
| 11 | { | ||
| 12 | halt (); | ||
| 13 | /* not reached */ | ||
| 14 | } | ||
diff --git a/examples/hello.c b/examples/hello.c new file mode 100644 index 0000000..a12fd94 --- /dev/null +++ b/examples/hello.c | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <syscall.h> | ||
| 3 | |||
| 4 | int | ||
| 5 | main (int argc, char **argv) | ||
| 6 | { | ||
| 7 | printf ("Hello World :)\n"); | ||
| 8 | return EXIT_SUCCESS; | ||
| 9 | } | ||
diff --git a/examples/hex-dump.c b/examples/hex-dump.c new file mode 100644 index 0000000..ee313f2 --- /dev/null +++ b/examples/hex-dump.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* hex-dump.c | ||
| 2 | |||
| 3 | Prints files specified on command line to the console in hex. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | bool success = true; | ||
| 12 | int i; | ||
| 13 | |||
| 14 | for (i = 1; i < argc; i++) | ||
| 15 | { | ||
| 16 | int fd = open (argv[i]); | ||
| 17 | if (fd < 0) | ||
| 18 | { | ||
| 19 | printf ("%s: open failed\n", argv[i]); | ||
| 20 | success = false; | ||
| 21 | continue; | ||
| 22 | } | ||
| 23 | for (;;) | ||
| 24 | { | ||
| 25 | char buffer[1024]; | ||
| 26 | int pos = tell (fd); | ||
| 27 | int bytes_read = read (fd, buffer, sizeof buffer); | ||
| 28 | if (bytes_read == 0) | ||
| 29 | break; | ||
| 30 | hex_dump (pos, buffer, bytes_read, true); | ||
| 31 | } | ||
| 32 | close (fd); | ||
| 33 | } | ||
| 34 | return success ? EXIT_SUCCESS : EXIT_FAILURE; | ||
| 35 | } | ||
diff --git a/examples/insult.c b/examples/insult.c new file mode 100644 index 0000000..98c4e6a --- /dev/null +++ b/examples/insult.c | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | /* Insult.c | ||
| 2 | |||
| 3 | This is a version of the famous CS 107 random sentence | ||
| 4 | generator. I wrote a program that reads a grammar definition | ||
| 5 | file and writes a C file containing that grammar as hard code | ||
| 6 | static C strings. Thus the majority of the code below in | ||
| 7 | machine generated and totally unreadable. The arrays created | ||
| 8 | are specially designed to make generating the sentences as | ||
| 9 | easy as possible. | ||
| 10 | |||
| 11 | Originally by Greg Hutchins, March 1998. | ||
| 12 | Modified by Ben Pfaff for Pintos, Sept 2004. */ | ||
| 13 | char *start[] = | ||
| 14 | { "You", "1", "5", ".", "May", "13", ".", "With", "the", "19", "of", "18", | ||
| 15 | ",", "may", "13", "." | ||
| 16 | }; | ||
| 17 | char startLoc[] = { 3, 0, 4, 7, 16 }; | ||
| 18 | char *adj[] = { "3", "4", "2", ",", "1" }; | ||
| 19 | char adjLoc[] = { 3, 0, 1, 2, 5 }; | ||
| 20 | char *adj3[] = { "3", "4" }; | ||
| 21 | char adj3Loc[] = { 2, 0, 1, 2 }; | ||
| 22 | char *adj1[] = | ||
| 23 | { "lame", "dried", "up", "par-broiled", "bloated", "half-baked", "spiteful", | ||
| 24 | "egotistical", "ungrateful", "stupid", "moronic", "fat", "ugly", "puny", "pitiful", | ||
| 25 | "insignificant", "blithering", "repulsive", "worthless", "blundering", "retarded", | ||
| 26 | "useless", "obnoxious", "low-budget", "assinine", "neurotic", "subhuman", "crochety", | ||
| 27 | "indescribable", "contemptible", "unspeakable", "sick", "lazy", "good-for-nothing", | ||
| 28 | "slutty", "mentally-deficient", "creepy", "sloppy", "dismal", "pompous", "pathetic", | ||
| 29 | "friendless", "revolting", "slovenly", "cantankerous", "uncultured", "insufferable", | ||
| 30 | "gross", "unkempt", "defective", "crumby" | ||
| 31 | }; | ||
| 32 | char adj1Loc[] = | ||
| 33 | { 50, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, | ||
| 34 | 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, | ||
| 35 | 43, 44, 45, 46, 47, 48, 49, 50, 51 }; | ||
| 36 | char *adj2[] = | ||
| 37 | { "putrefied", "festering", "funky", "moldy", "leprous", "curdled", "fetid", | ||
| 38 | "slimy", "crusty", "sweaty", "damp", "deranged", "smelly", "stenchy", "malignant", | ||
| 39 | "noxious", "grimy", "reeky", "nasty", "mutilated", "sloppy", "gruesome", "grisly", | ||
| 40 | "sloshy", "wormy", "mealy", "spoiled", "contaminated", "rancid", "musty", | ||
| 41 | "fly-covered", "moth-eaten", "decaying", "decomposed", "freeze-dried", "defective", | ||
| 42 | "petrified", "rotting", "scabrous", "hirsute" | ||
| 43 | }; | ||
| 44 | char adj2Loc[] = | ||
| 45 | { 40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, | ||
| 46 | 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 }; | ||
| 47 | char *name[] = | ||
| 48 | { "10", ",", "bad", "excuse", "for", "6", ",", "6", "for", "brains", ",", | ||
| 49 | "4", "11", "8", "for", "brains", "offspring", "of", "a", "motherless", "10", "7", "6", | ||
| 50 | "7", "4", "11", "8" | ||
| 51 | }; | ||
| 52 | char nameLoc[] = { 7, 0, 1, 6, 10, 16, 21, 23, 27 }; | ||
| 53 | char *stuff[] = | ||
| 54 | { "shit", "toe", "jam", "filth", "puss", "earwax", "leaf", "clippings", | ||
| 55 | "bat", "guano", "mucus", "fungus", "mung", "refuse", "earwax", "spittoon", "spittle", | ||
| 56 | "phlegm" | ||
| 57 | }; | ||
| 58 | char stuffLoc[] = { 14, 0, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15, 17, 18 }; | ||
| 59 | char *noun_and_prep[] = | ||
| 60 | { "bit", "of", "piece", "of", "vat", "of", "lump", "of", "crock", "of", | ||
| 61 | "ball", "of", "tub", "of", "load", "of", "bucket", "of", "mound", "of", "glob", "of", "bag", | ||
| 62 | "of", "heap", "of", "mountain", "of", "load", "of", "barrel", "of", "sack", "of", "blob", "of", | ||
| 63 | "pile", "of", "truckload", "of", "vat", "of" | ||
| 64 | }; | ||
| 65 | char noun_and_prepLoc[] = | ||
| 66 | { 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, | ||
| 67 | 38, 40, 42 }; | ||
| 68 | char *organics[] = | ||
| 69 | { "droppings", "mung", "zits", "puckies", "tumors", "cysts", "tumors", | ||
| 70 | "livers", "froth", "parts", "scabs", "guts", "entrails", "blubber", "carcuses", "gizards", | ||
| 71 | "9" | ||
| 72 | }; | ||
| 73 | char organicsLoc[] = | ||
| 74 | { 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; | ||
| 75 | char *body_parts[] = | ||
| 76 | { "kidneys", "genitals", "buttocks", "earlobes", "innards", "feet" | ||
| 77 | }; | ||
| 78 | char body_partsLoc[] = { 6, 0, 1, 2, 3, 4, 5, 6 }; | ||
| 79 | char *noun[] = | ||
| 80 | { "pop", "tart", "warthog", "twinkie", "barnacle", "fondue", "pot", | ||
| 81 | "cretin", "fuckwad", "moron", "ass", "neanderthal", "nincompoop", "simpleton", "11" | ||
| 82 | }; | ||
| 83 | char nounLoc[] = { 13, 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; | ||
| 84 | char *animal[] = | ||
| 85 | { "donkey", "llama", "dingo", "lizard", "gekko", "lemur", "moose", "camel", | ||
| 86 | "goat", "eel" | ||
| 87 | }; | ||
| 88 | char animalLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | ||
| 89 | char *good_verb[] = | ||
| 90 | { "love", "cuddle", "fondle", "adore", "smooch", "hug", "caress", "worship", | ||
| 91 | "look", "at", "touch" | ||
| 92 | }; | ||
| 93 | char good_verbLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 }; | ||
| 94 | char *curse[] = | ||
| 95 | { "14", "20", "23", "14", "17", "20", "23", "14", "find", "your", "9", | ||
| 96 | "suddenly", "delectable", "14", "and", "14", "seek", "a", "battleground", "23" | ||
| 97 | }; | ||
| 98 | char curseLoc[] = { 4, 0, 3, 7, 13, 20 }; | ||
| 99 | char *afflictors[] = | ||
| 100 | { "15", "21", "15", "21", "15", "21", "15", "21", "a", "22", "Rush", | ||
| 101 | "Limbaugh", "the", "hosts", "of", "Hades" | ||
| 102 | }; | ||
| 103 | char afflictorsLoc[] = { 6, 0, 2, 4, 6, 8, 12, 16 }; | ||
| 104 | char *quantity[] = | ||
| 105 | { "a", "4", "hoard", "of", "a", "4", "pack", "of", "a", "truckload", "of", | ||
| 106 | "a", "swarm", "of", "many", "an", "army", "of", "a", "4", "heard", "of", "a", "4", | ||
| 107 | "platoon", "of", "a", "4", "and", "4", "group", "of", "16" | ||
| 108 | }; | ||
| 109 | char quantityLoc[] = { 10, 0, 4, 8, 11, 14, 15, 18, 22, 26, 32, 33 }; | ||
| 110 | char *numbers[] = | ||
| 111 | { "a", "thousand", "three", "million", "ninty-nine", "nine-hundred,", | ||
| 112 | "ninty-nine", "forty-two", "a", "gazillion", "sixty-eight", "times", "thirty-three" | ||
| 113 | }; | ||
| 114 | char numbersLoc[] = { 7, 0, 2, 4, 5, 7, 8, 10, 13 }; | ||
| 115 | char *adv[] = | ||
| 116 | { "viciously", "manicly", "merrily", "happily", ",", "with", "the", "19", | ||
| 117 | "of", "18", ",", "gleefully", ",", "with", "much", "ritualistic", "celebration", ",", | ||
| 118 | "franticly" | ||
| 119 | }; | ||
| 120 | char advLoc[] = { 8, 0, 1, 2, 3, 4, 11, 12, 18, 19 }; | ||
| 121 | char *metaphor[] = | ||
| 122 | { "an", "irate", "manticore", "Thor's", "belch", "Alah's", "fist", "16", | ||
| 123 | "titans", "a", "particularly", "vicious", "she-bear", "in", "the", "midst", "of", "her", | ||
| 124 | "menstrual", "cycle", "a", "pissed-off", "Jabberwock" | ||
| 125 | }; | ||
| 126 | char metaphorLoc[] = { 6, 0, 3, 5, 7, 9, 20, 23 }; | ||
| 127 | char *force[] = { "force", "fury", "power", "rage" }; | ||
| 128 | char forceLoc[] = { 4, 0, 1, 2, 3, 4 }; | ||
| 129 | char *bad_action[] = | ||
| 130 | { "spit", "shimmy", "slobber", "find", "refuge", "find", "shelter", "dance", | ||
| 131 | "retch", "vomit", "defecate", "erect", "a", "strip", "mall", "build", "a", "26", "have", "a", | ||
| 132 | "religious", "experience", "discharge", "bodily", "waste", "fart", "dance", "drool", | ||
| 133 | "lambada", "spill", "16", "rusty", "tacks", "bite", "you", "sneeze", "sing", "16", | ||
| 134 | "campfire", "songs", "smite", "you", "16", "times", "construct", "a", "new", "home", "throw", | ||
| 135 | "a", "party", "procreate" | ||
| 136 | }; | ||
| 137 | char bad_actionLoc[] = | ||
| 138 | { 25, 0, 1, 2, 3, 5, 7, 8, 9, 10, 11, 15, 18, 22, 25, 26, 27, 28, 29, 33, | ||
| 139 | 35, 36, 40, 44, 48, 51, 52 }; | ||
| 140 | char *beasties[] = | ||
| 141 | { "yaks", "22", "maggots", "22", "cockroaches", "stinging", "scorpions", | ||
| 142 | "fleas", "22", "weasels", "22", "gnats", "South", "American", "killer", "bees", "spiders", | ||
| 143 | "4", "monkeys", "22", "wiener-dogs", "22", "rats", "22", "wolverines", "4", ",", "22", | ||
| 144 | "pit-fiends" | ||
| 145 | }; | ||
| 146 | char beastiesLoc[] = | ||
| 147 | { 14, 0, 1, 3, 5, 7, 8, 10, 12, 16, 17, 19, 21, 23, 25, 29 }; | ||
| 148 | char *condition[] = | ||
| 149 | { "frothing", "manic", "crazed", "plague-ridden", "disease-carrying", | ||
| 150 | "biting", "rabid", "blood-thirsty", "ravaging", "slavering" | ||
| 151 | }; | ||
| 152 | char conditionLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | ||
| 153 | char *place[] = | ||
| 154 | { "in", "24", "25", "upon", "your", "mother's", "grave", "on", "24", "best", | ||
| 155 | "rug", "in", "the", "26", "you", "call", "home", "upon", "your", "heinie" | ||
| 156 | }; | ||
| 157 | char placeLoc[] = { 5, 0, 3, 7, 11, 17, 20 }; | ||
| 158 | char *relation[] = | ||
| 159 | { "your", "your", "your", "your", "father's", "your", "mother's", "your", | ||
| 160 | "grandma's" | ||
| 161 | }; | ||
| 162 | char relationLoc[] = { 6, 0, 1, 2, 3, 5, 7, 9 }; | ||
| 163 | char *in_something[] = | ||
| 164 | { "entrails", "anal", "cavity", "shoes", "house", "pantry", "general", | ||
| 165 | "direction", "pants", "bed" | ||
| 166 | }; | ||
| 167 | char in_somethingLoc[] = { 8, 0, 1, 3, 4, 5, 6, 8, 9, 10 }; | ||
| 168 | char *bad_place[] = | ||
| 169 | { "rat", "hole", "sewer", "toxic", "dump", "oil", "refinery", "landfill", | ||
| 170 | "porto-pottie" | ||
| 171 | }; | ||
| 172 | char bad_placeLoc[] = { 6, 0, 2, 3, 5, 7, 8, 9 }; | ||
| 173 | char **daGrammar[27]; | ||
| 174 | char *daGLoc[27]; | ||
| 175 | |||
| 176 | static void | ||
| 177 | init_grammar (void) | ||
| 178 | { | ||
| 179 | daGrammar[0] = start; | ||
| 180 | daGLoc[0] = startLoc; | ||
| 181 | daGrammar[1] = adj; | ||
| 182 | daGLoc[1] = adjLoc; | ||
| 183 | daGrammar[2] = adj3; | ||
| 184 | daGLoc[2] = adj3Loc; | ||
| 185 | daGrammar[3] = adj1; | ||
| 186 | daGLoc[3] = adj1Loc; | ||
| 187 | daGrammar[4] = adj2; | ||
| 188 | daGLoc[4] = adj2Loc; | ||
| 189 | daGrammar[5] = name; | ||
| 190 | daGLoc[5] = nameLoc; | ||
| 191 | daGrammar[6] = stuff; | ||
| 192 | daGLoc[6] = stuffLoc; | ||
| 193 | daGrammar[7] = noun_and_prep; | ||
| 194 | daGLoc[7] = noun_and_prepLoc; | ||
| 195 | daGrammar[8] = organics; | ||
| 196 | daGLoc[8] = organicsLoc; | ||
| 197 | daGrammar[9] = body_parts; | ||
| 198 | daGLoc[9] = body_partsLoc; | ||
| 199 | daGrammar[10] = noun; | ||
| 200 | daGLoc[10] = nounLoc; | ||
| 201 | daGrammar[11] = animal; | ||
| 202 | daGLoc[11] = animalLoc; | ||
| 203 | daGrammar[12] = good_verb; | ||
| 204 | daGLoc[12] = good_verbLoc; | ||
| 205 | daGrammar[13] = curse; | ||
| 206 | daGLoc[13] = curseLoc; | ||
| 207 | daGrammar[14] = afflictors; | ||
| 208 | daGLoc[14] = afflictorsLoc; | ||
| 209 | daGrammar[15] = quantity; | ||
| 210 | daGLoc[15] = quantityLoc; | ||
| 211 | daGrammar[16] = numbers; | ||
| 212 | daGLoc[16] = numbersLoc; | ||
| 213 | daGrammar[17] = adv; | ||
| 214 | daGLoc[17] = advLoc; | ||
| 215 | daGrammar[18] = metaphor; | ||
| 216 | daGLoc[18] = metaphorLoc; | ||
| 217 | daGrammar[19] = force; | ||
| 218 | daGLoc[19] = forceLoc; | ||
| 219 | daGrammar[20] = bad_action; | ||
| 220 | daGLoc[20] = bad_actionLoc; | ||
| 221 | daGrammar[21] = beasties; | ||
| 222 | daGLoc[21] = beastiesLoc; | ||
| 223 | daGrammar[22] = condition; | ||
| 224 | daGLoc[22] = conditionLoc; | ||
| 225 | daGrammar[23] = place; | ||
| 226 | daGLoc[23] = placeLoc; | ||
| 227 | daGrammar[24] = relation; | ||
| 228 | daGLoc[24] = relationLoc; | ||
| 229 | daGrammar[25] = in_something; | ||
| 230 | daGLoc[25] = in_somethingLoc; | ||
| 231 | daGrammar[26] = bad_place; | ||
| 232 | daGLoc[26] = bad_placeLoc; | ||
| 233 | } | ||
| 234 | |||
| 235 | #include <ctype.h> | ||
| 236 | #include <debug.h> | ||
| 237 | #include <random.h> | ||
| 238 | #include <stdio.h> | ||
| 239 | #include <stdlib.h> | ||
| 240 | #include <string.h> | ||
| 241 | #include <syscall.h> | ||
| 242 | |||
| 243 | void expand (int num, char **grammar[], char *location[], int handle); | ||
| 244 | |||
| 245 | static void | ||
| 246 | usage (int ret_code, const char *message, ...) PRINTF_FORMAT (2, 3); | ||
| 247 | |||
| 248 | static void | ||
| 249 | usage (int ret_code, const char *message, ...) | ||
| 250 | { | ||
| 251 | va_list args; | ||
| 252 | |||
| 253 | if (message != NULL) | ||
| 254 | { | ||
| 255 | va_start (args, message); | ||
| 256 | vprintf (message, args); | ||
| 257 | va_end (args); | ||
| 258 | } | ||
| 259 | |||
| 260 | printf ("\n" | ||
| 261 | "Usage: insult [OPTION]...\n" | ||
| 262 | "Prints random insults to screen.\n\n" | ||
| 263 | " -h: this help message\n" | ||
| 264 | " -s <integer>: set the random seed (default 4951)\n" | ||
| 265 | " -n <integer>: choose number of insults (default 4)\n" | ||
| 266 | " -f <file>: redirect output to <file>\n"); | ||
| 267 | |||
| 268 | exit (ret_code); | ||
| 269 | } | ||
| 270 | |||
| 271 | int | ||
| 272 | main (int argc, char *argv[]) | ||
| 273 | { | ||
| 274 | int sentence_cnt, new_seed, i, file_flag, sent_flag, seed_flag; | ||
| 275 | int handle; | ||
| 276 | |||
| 277 | new_seed = 4951; | ||
| 278 | sentence_cnt = 4; | ||
| 279 | file_flag = 0; | ||
| 280 | seed_flag = 0; | ||
| 281 | sent_flag = 0; | ||
| 282 | handle = STDOUT_FILENO; | ||
| 283 | |||
| 284 | for (i = 1; i < argc; i++) | ||
| 285 | { | ||
| 286 | if (strcmp (argv[1], "-h") == 0) | ||
| 287 | usage (0, NULL); | ||
| 288 | else if (strcmp (argv[i], "-s") == 0) | ||
| 289 | { | ||
| 290 | if (seed_flag++) | ||
| 291 | usage (-1, "Can't have more than one seed"); | ||
| 292 | if (++i >= argc) | ||
| 293 | usage (-1, "Missing value for -s"); | ||
| 294 | new_seed = atoi (argv[i]); | ||
| 295 | } | ||
| 296 | else if (strcmp (argv[i], "-n") == 0) | ||
| 297 | { | ||
| 298 | if (sent_flag++) | ||
| 299 | usage (-1, "Can't have more than one sentence option"); | ||
| 300 | if (++i >= argc) | ||
| 301 | usage (-1, "Missing value for -n"); | ||
| 302 | sentence_cnt = atoi (argv[i]); | ||
| 303 | if (sentence_cnt < 1) | ||
| 304 | usage (-1, "Must have at least one sentence"); | ||
| 305 | } | ||
| 306 | else if (strcmp (argv[i], "-f") == 0) | ||
| 307 | { | ||
| 308 | if (file_flag++) | ||
| 309 | usage (-1, "Can't have more than one output file"); | ||
| 310 | if (++i >= argc) | ||
| 311 | usage (-1, "Missing value for -f"); | ||
| 312 | |||
| 313 | /* Because files have fixed length in the basic Pintos | ||
| 314 | file system, the 0 argument means that this option | ||
| 315 | will not be useful until project 4 is | ||
| 316 | implemented. */ | ||
| 317 | create (argv[i], 0); | ||
| 318 | handle = open (argv[i]); | ||
| 319 | if (handle < 0) | ||
| 320 | { | ||
| 321 | printf ("%s: open failed\n", argv[i]); | ||
| 322 | return EXIT_FAILURE; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | else | ||
| 326 | usage (-1, "Unrecognized flag"); | ||
| 327 | } | ||
| 328 | |||
| 329 | init_grammar (); | ||
| 330 | |||
| 331 | random_init (new_seed); | ||
| 332 | hprintf (handle, "\n"); | ||
| 333 | |||
| 334 | for (i = 0; i < sentence_cnt; i++) | ||
| 335 | { | ||
| 336 | hprintf (handle, "\n"); | ||
| 337 | expand (0, daGrammar, daGLoc, handle); | ||
| 338 | hprintf (handle, "\n\n"); | ||
| 339 | } | ||
| 340 | |||
| 341 | if (file_flag) | ||
| 342 | close (handle); | ||
| 343 | |||
| 344 | return EXIT_SUCCESS; | ||
| 345 | } | ||
| 346 | |||
| 347 | void | ||
| 348 | expand (int num, char **grammar[], char *location[], int handle) | ||
| 349 | { | ||
| 350 | char *word; | ||
| 351 | int i, which, listStart, listEnd; | ||
| 352 | |||
| 353 | which = random_ulong () % location[num][0] + 1; | ||
| 354 | listStart = location[num][which]; | ||
| 355 | listEnd = location[num][which + 1]; | ||
| 356 | for (i = listStart; i < listEnd; i++) | ||
| 357 | { | ||
| 358 | word = grammar[num][i]; | ||
| 359 | if (!isdigit (*word)) | ||
| 360 | { | ||
| 361 | if (!ispunct (*word)) | ||
| 362 | hprintf (handle, " "); | ||
| 363 | hprintf (handle, "%s", word); | ||
| 364 | } | ||
| 365 | else | ||
| 366 | expand (atoi (word), grammar, location, handle); | ||
| 367 | } | ||
| 368 | |||
| 369 | } | ||
diff --git a/examples/lib/.gitignore b/examples/lib/.gitignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/examples/lib/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| *.d | |||
diff --git a/examples/lib/user/.dummy b/examples/lib/user/.dummy new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/examples/lib/user/.dummy | |||
diff --git a/examples/lib/user/.gitignore b/examples/lib/user/.gitignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/examples/lib/user/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| *.d | |||
diff --git a/examples/lineup.c b/examples/lineup.c new file mode 100644 index 0000000..60402d0 --- /dev/null +++ b/examples/lineup.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* lineup.c | ||
| 2 | |||
| 3 | Converts a file to uppercase in-place. | ||
| 4 | |||
| 5 | Incidentally, another way to do this while avoiding the seeks | ||
| 6 | would be to open the input file, then remove() it and reopen | ||
| 7 | it under another handle. Because of Unix deletion semantics | ||
| 8 | this works fine. */ | ||
| 9 | |||
| 10 | #include <ctype.h> | ||
| 11 | #include <stdio.h> | ||
| 12 | #include <syscall.h> | ||
| 13 | |||
| 14 | int | ||
| 15 | main (int argc, char *argv[]) | ||
| 16 | { | ||
| 17 | char buf[1024]; | ||
| 18 | int handle; | ||
| 19 | |||
| 20 | if (argc != 2) | ||
| 21 | exit (1); | ||
| 22 | |||
| 23 | handle = open (argv[1]); | ||
| 24 | if (handle < 0) | ||
| 25 | exit (2); | ||
| 26 | |||
| 27 | for (;;) | ||
| 28 | { | ||
| 29 | int n, i; | ||
| 30 | |||
| 31 | n = read (handle, buf, sizeof buf); | ||
| 32 | if (n <= 0) | ||
| 33 | break; | ||
| 34 | |||
| 35 | for (i = 0; i < n; i++) | ||
| 36 | buf[i] = toupper ((unsigned char) buf[i]); | ||
| 37 | |||
| 38 | seek (handle, tell (handle) - n); | ||
| 39 | if (write (handle, buf, n) != n) | ||
| 40 | printf ("write failed\n"); | ||
| 41 | } | ||
| 42 | |||
| 43 | close (handle); | ||
| 44 | |||
| 45 | return EXIT_SUCCESS; | ||
| 46 | } | ||
diff --git a/examples/ls.c b/examples/ls.c new file mode 100644 index 0000000..fbe27a1 --- /dev/null +++ b/examples/ls.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* ls.c | ||
| 2 | |||
| 3 | Lists the contents of the directory or directories named on | ||
| 4 | the command line, or of the current directory if none are | ||
| 5 | named. | ||
| 6 | |||
| 7 | By default, only the name of each file is printed. If "-l" is | ||
| 8 | given as the first argument, the type, size, and inumber of | ||
| 9 | each file is also printed. This won't work until project 4. */ | ||
| 10 | |||
| 11 | #include <syscall.h> | ||
| 12 | #include <stdio.h> | ||
| 13 | #include <string.h> | ||
| 14 | |||
| 15 | static bool | ||
| 16 | list_dir (const char *dir, bool verbose) | ||
| 17 | { | ||
| 18 | int dir_fd = open (dir); | ||
| 19 | if (dir_fd == -1) | ||
| 20 | { | ||
| 21 | printf ("%s: not found\n", dir); | ||
| 22 | return false; | ||
| 23 | } | ||
| 24 | |||
| 25 | if (isdir (dir_fd)) | ||
| 26 | { | ||
| 27 | char name[READDIR_MAX_LEN]; | ||
| 28 | |||
| 29 | printf ("%s", dir); | ||
| 30 | if (verbose) | ||
| 31 | printf (" (inumber %d)", inumber (dir_fd)); | ||
| 32 | printf (":\n"); | ||
| 33 | |||
| 34 | while (readdir (dir_fd, name)) | ||
| 35 | { | ||
| 36 | printf ("%s", name); | ||
| 37 | if (verbose) | ||
| 38 | { | ||
| 39 | char full_name[128]; | ||
| 40 | int entry_fd; | ||
| 41 | |||
| 42 | snprintf (full_name, sizeof full_name, "%s/%s", dir, name); | ||
| 43 | entry_fd = open (full_name); | ||
| 44 | |||
| 45 | printf (": "); | ||
| 46 | if (entry_fd != -1) | ||
| 47 | { | ||
| 48 | if (isdir (entry_fd)) | ||
| 49 | printf ("directory"); | ||
| 50 | else | ||
| 51 | printf ("%d-byte file", filesize (entry_fd)); | ||
| 52 | printf (", inumber %d", inumber (entry_fd)); | ||
| 53 | } | ||
| 54 | else | ||
| 55 | printf ("open failed"); | ||
| 56 | close (entry_fd); | ||
| 57 | } | ||
| 58 | printf ("\n"); | ||
| 59 | } | ||
| 60 | } | ||
| 61 | else | ||
| 62 | printf ("%s: not a directory\n", dir); | ||
| 63 | close (dir_fd); | ||
| 64 | return true; | ||
| 65 | } | ||
| 66 | |||
| 67 | int | ||
| 68 | main (int argc, char *argv[]) | ||
| 69 | { | ||
| 70 | bool success = true; | ||
| 71 | bool verbose = false; | ||
| 72 | |||
| 73 | if (argc > 1 && !strcmp (argv[1], "-l")) | ||
| 74 | { | ||
| 75 | verbose = true; | ||
| 76 | argv++; | ||
| 77 | argc--; | ||
| 78 | } | ||
| 79 | |||
| 80 | if (argc <= 1) | ||
| 81 | success = list_dir (".", verbose); | ||
| 82 | else | ||
| 83 | { | ||
| 84 | int i; | ||
| 85 | for (i = 1; i < argc; i++) | ||
| 86 | if (!list_dir (argv[i], verbose)) | ||
| 87 | success = false; | ||
| 88 | } | ||
| 89 | return success ? EXIT_SUCCESS : EXIT_FAILURE; | ||
| 90 | } | ||
diff --git a/examples/matmult.c b/examples/matmult.c new file mode 100644 index 0000000..4f0615f --- /dev/null +++ b/examples/matmult.c | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* matmult.c | ||
| 2 | |||
| 3 | Test program to do matrix multiplication on large arrays. | ||
| 4 | |||
| 5 | Intended to stress virtual memory system. | ||
| 6 | |||
| 7 | Ideally, we could read the matrices off of the file system, | ||
| 8 | and store the result back to the file system! | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <stdio.h> | ||
| 12 | #include <syscall.h> | ||
| 13 | |||
| 14 | /* You should define DIM to be large enough that the arrays | ||
| 15 | don't fit in physical memory. | ||
| 16 | |||
| 17 | Dim Memory | ||
| 18 | ------ -------- | ||
| 19 | 16 3 kB | ||
| 20 | 64 48 kB | ||
| 21 | 128 192 kB | ||
| 22 | 256 768 kB | ||
| 23 | 512 3,072 kB | ||
| 24 | 1,024 12,288 kB | ||
| 25 | 2,048 49,152 kB | ||
| 26 | 4,096 196,608 kB | ||
| 27 | 8,192 786,432 kB | ||
| 28 | 16,384 3,145,728 kB */ | ||
| 29 | #define DIM 128 | ||
| 30 | |||
| 31 | int A[DIM][DIM]; | ||
| 32 | int B[DIM][DIM]; | ||
| 33 | int C[DIM][DIM]; | ||
| 34 | |||
| 35 | int | ||
| 36 | main (void) | ||
| 37 | { | ||
| 38 | int i, j, k; | ||
| 39 | |||
| 40 | /* Initialize the matrices. */ | ||
| 41 | for (i = 0; i < DIM; i++) | ||
| 42 | for (j = 0; j < DIM; j++) | ||
| 43 | { | ||
| 44 | A[i][j] = i; | ||
| 45 | B[i][j] = j; | ||
| 46 | C[i][j] = 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | /* Multiply matrices. */ | ||
| 50 | for (i = 0; i < DIM; i++) | ||
| 51 | for (j = 0; j < DIM; j++) | ||
| 52 | for (k = 0; k < DIM; k++) | ||
| 53 | C[i][j] += A[i][k] * B[k][j]; | ||
| 54 | |||
| 55 | /* Done. */ | ||
| 56 | exit (C[DIM - 1][DIM - 1]); | ||
| 57 | } | ||
diff --git a/examples/mcat.c b/examples/mcat.c new file mode 100644 index 0000000..7b39760 --- /dev/null +++ b/examples/mcat.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* mcat.c | ||
| 2 | |||
| 3 | Prints files specified on command line to the console, using | ||
| 4 | mmap. */ | ||
| 5 | |||
| 6 | #include <stdio.h> | ||
| 7 | #include <syscall.h> | ||
| 8 | |||
| 9 | int | ||
| 10 | main (int argc, char *argv[]) | ||
| 11 | { | ||
| 12 | int i; | ||
| 13 | |||
| 14 | for (i = 1; i < argc; i++) | ||
| 15 | { | ||
| 16 | int fd; | ||
| 17 | mapid_t map; | ||
| 18 | void *data = (void *) 0x10000000; | ||
| 19 | int size; | ||
| 20 | |||
| 21 | /* Open input file. */ | ||
| 22 | fd = open (argv[i]); | ||
| 23 | if (fd < 0) | ||
| 24 | { | ||
| 25 | printf ("%s: open failed\n", argv[i]); | ||
| 26 | return EXIT_FAILURE; | ||
| 27 | } | ||
| 28 | size = filesize (fd); | ||
| 29 | |||
| 30 | /* Map files. */ | ||
| 31 | map = mmap (fd, data); | ||
| 32 | if (map == MAP_FAILED) | ||
| 33 | { | ||
| 34 | printf ("%s: mmap failed\n", argv[i]); | ||
| 35 | return EXIT_FAILURE; | ||
| 36 | } | ||
| 37 | |||
| 38 | /* Write file to console. */ | ||
| 39 | write (STDOUT_FILENO, data, size); | ||
| 40 | |||
| 41 | /* Unmap files (optional). */ | ||
| 42 | munmap (map); | ||
| 43 | } | ||
| 44 | return EXIT_SUCCESS; | ||
| 45 | } | ||
diff --git a/examples/mcp.c b/examples/mcp.c new file mode 100644 index 0000000..6091dc8 --- /dev/null +++ b/examples/mcp.c | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* mcp.c | ||
| 2 | |||
| 3 | Copies one file to another, using mmap. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include <syscall.h> | ||
| 8 | |||
| 9 | int | ||
| 10 | main (int argc, char *argv[]) | ||
| 11 | { | ||
| 12 | int in_fd, out_fd; | ||
| 13 | mapid_t in_map, out_map; | ||
| 14 | void *in_data = (void *) 0x10000000; | ||
| 15 | void *out_data = (void *) 0x20000000; | ||
| 16 | int size; | ||
| 17 | |||
| 18 | if (argc != 3) | ||
| 19 | { | ||
| 20 | printf ("usage: cp OLD NEW\n"); | ||
| 21 | return EXIT_FAILURE; | ||
| 22 | } | ||
| 23 | |||
| 24 | /* Open input file. */ | ||
| 25 | in_fd = open (argv[1]); | ||
| 26 | if (in_fd < 0) | ||
| 27 | { | ||
| 28 | printf ("%s: open failed\n", argv[1]); | ||
| 29 | return EXIT_FAILURE; | ||
| 30 | } | ||
| 31 | size = filesize (in_fd); | ||
| 32 | |||
| 33 | /* Create and open output file. */ | ||
| 34 | if (!create (argv[2], size)) | ||
| 35 | { | ||
| 36 | printf ("%s: create failed\n", argv[2]); | ||
| 37 | return EXIT_FAILURE; | ||
| 38 | } | ||
| 39 | out_fd = open (argv[2]); | ||
| 40 | if (out_fd < 0) | ||
| 41 | { | ||
| 42 | printf ("%s: open failed\n", argv[2]); | ||
| 43 | return EXIT_FAILURE; | ||
| 44 | } | ||
| 45 | |||
| 46 | /* Map files. */ | ||
| 47 | in_map = mmap (in_fd, in_data); | ||
| 48 | if (in_map == MAP_FAILED) | ||
| 49 | { | ||
| 50 | printf ("%s: mmap failed\n", argv[1]); | ||
| 51 | return EXIT_FAILURE; | ||
| 52 | } | ||
| 53 | out_map = mmap (out_fd, out_data); | ||
| 54 | if (out_map == MAP_FAILED) | ||
| 55 | { | ||
| 56 | printf ("%s: mmap failed\n", argv[2]); | ||
| 57 | return EXIT_FAILURE; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Copy files. */ | ||
| 61 | memcpy (out_data, in_data, size); | ||
| 62 | |||
| 63 | /* Unmap files (optional). */ | ||
| 64 | munmap (in_map); | ||
| 65 | munmap (out_map); | ||
| 66 | |||
| 67 | return EXIT_SUCCESS; | ||
| 68 | } | ||
diff --git a/examples/mkdir.c b/examples/mkdir.c new file mode 100644 index 0000000..7ddbc3f --- /dev/null +++ b/examples/mkdir.c | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | /* mkdir.c | ||
| 2 | |||
| 3 | Creates a directory. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | if (argc != 2) | ||
| 12 | { | ||
| 13 | printf ("usage: %s DIRECTORY\n", argv[0]); | ||
| 14 | return EXIT_FAILURE; | ||
| 15 | } | ||
| 16 | |||
| 17 | if (!mkdir (argv[1])) | ||
| 18 | { | ||
| 19 | printf ("%s: mkdir failed\n", argv[1]); | ||
| 20 | return EXIT_FAILURE; | ||
| 21 | } | ||
| 22 | |||
| 23 | return EXIT_SUCCESS; | ||
| 24 | } | ||
diff --git a/examples/pwd.c b/examples/pwd.c new file mode 100644 index 0000000..d2305cf --- /dev/null +++ b/examples/pwd.c | |||
| @@ -0,0 +1,152 @@ | |||
| 1 | /* pwd.c | ||
| 2 | |||
| 3 | Prints the absolute name of the present working directory. */ | ||
| 4 | |||
| 5 | #include <syscall.h> | ||
| 6 | #include <stdbool.h> | ||
| 7 | #include <stdio.h> | ||
| 8 | #include <string.h> | ||
| 9 | |||
| 10 | static bool getcwd (char *cwd, size_t cwd_size); | ||
| 11 | |||
| 12 | int | ||
| 13 | main (void) | ||
| 14 | { | ||
| 15 | char cwd[128]; | ||
| 16 | if (getcwd (cwd, sizeof cwd)) | ||
| 17 | { | ||
| 18 | printf ("%s\n", cwd); | ||
| 19 | return EXIT_SUCCESS; | ||
| 20 | } | ||
| 21 | else | ||
| 22 | { | ||
| 23 | printf ("error\n"); | ||
| 24 | return EXIT_FAILURE; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | /* Stores the inode number for FILE_NAME in *INUM. | ||
| 29 | Returns true if successful, false if the file could not be | ||
| 30 | opened. */ | ||
| 31 | static bool | ||
| 32 | get_inumber (const char *file_name, int *inum) | ||
| 33 | { | ||
| 34 | int fd = open (file_name); | ||
| 35 | if (fd >= 0) | ||
| 36 | { | ||
| 37 | *inum = inumber (fd); | ||
| 38 | close (fd); | ||
| 39 | return true; | ||
| 40 | } | ||
| 41 | else | ||
| 42 | return false; | ||
| 43 | } | ||
| 44 | |||
| 45 | /* Prepends PREFIX to the characters stored in the final *DST_LEN | ||
| 46 | bytes of the DST_SIZE-byte buffer that starts at DST. | ||
| 47 | Returns true if successful, false if adding that many | ||
| 48 | characters, plus a null terminator, would overflow the buffer. | ||
| 49 | (No null terminator is actually added or depended upon, but | ||
| 50 | its space is accounted for.) */ | ||
| 51 | static bool | ||
| 52 | prepend (const char *prefix, | ||
| 53 | char *dst, size_t *dst_len, size_t dst_size) | ||
| 54 | { | ||
| 55 | size_t prefix_len = strlen (prefix); | ||
| 56 | if (prefix_len + *dst_len + 1 <= dst_size) | ||
| 57 | { | ||
| 58 | *dst_len += prefix_len; | ||
| 59 | memcpy ((dst + dst_size) - *dst_len, prefix, prefix_len); | ||
| 60 | return true; | ||
| 61 | } | ||
| 62 | else | ||
| 63 | return false; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* Stores the current working directory, as a null-terminated | ||
| 67 | string, in the CWD_SIZE bytes in CWD. | ||
| 68 | Returns true if successful, false on error. Errors include | ||
| 69 | system errors, directory trees deeper than MAX_LEVEL levels, | ||
| 70 | and insufficient space in CWD. */ | ||
| 71 | static bool | ||
| 72 | getcwd (char *cwd, size_t cwd_size) | ||
| 73 | { | ||
| 74 | size_t cwd_len = 0; | ||
| 75 | |||
| 76 | #define MAX_LEVEL 20 | ||
| 77 | char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1]; | ||
| 78 | char *namep; | ||
| 79 | |||
| 80 | int child_inum; | ||
| 81 | |||
| 82 | /* Make sure there's enough space for at least "/". */ | ||
| 83 | if (cwd_size < 2) | ||
| 84 | return false; | ||
| 85 | |||
| 86 | /* Get inumber for current directory. */ | ||
| 87 | if (!get_inumber (".", &child_inum)) | ||
| 88 | return false; | ||
| 89 | |||
| 90 | namep = name; | ||
| 91 | for (;;) | ||
| 92 | { | ||
| 93 | int parent_inum, parent_fd; | ||
| 94 | |||
| 95 | /* Compose "../../../..", etc., in NAME. */ | ||
| 96 | if ((namep - name) > MAX_LEVEL * 3) | ||
| 97 | return false; | ||
| 98 | *namep++ = '.'; | ||
| 99 | *namep++ = '.'; | ||
| 100 | *namep = '\0'; | ||
| 101 | |||
| 102 | /* Open directory. */ | ||
| 103 | parent_fd = open (name); | ||
| 104 | if (parent_fd < 0) | ||
| 105 | return false; | ||
| 106 | *namep++ = '/'; | ||
| 107 | |||
| 108 | /* If parent and child have the same inumber, | ||
| 109 | then we've arrived at the root. */ | ||
| 110 | parent_inum = inumber (parent_fd); | ||
| 111 | if (parent_inum == child_inum) | ||
| 112 | break; | ||
| 113 | |||
| 114 | /* Find name of file in parent directory with the child's | ||
| 115 | inumber. */ | ||
| 116 | for (;;) | ||
| 117 | { | ||
| 118 | int test_inum; | ||
| 119 | if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum)) | ||
| 120 | { | ||
| 121 | close (parent_fd); | ||
| 122 | return false; | ||
| 123 | } | ||
| 124 | if (test_inum == child_inum) | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | close (parent_fd); | ||
| 128 | |||
| 129 | /* Prepend "/name" to CWD. */ | ||
| 130 | if (!prepend (namep - 1, cwd, &cwd_len, cwd_size)) | ||
| 131 | return false; | ||
| 132 | |||
| 133 | /* Move up. */ | ||
| 134 | child_inum = parent_inum; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* Finalize CWD. */ | ||
| 138 | if (cwd_len > 0) | ||
| 139 | { | ||
| 140 | /* Move the string to the beginning of CWD, | ||
| 141 | and null-terminate it. */ | ||
| 142 | memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len); | ||
| 143 | cwd[cwd_len] = '\0'; | ||
| 144 | } | ||
| 145 | else | ||
| 146 | { | ||
| 147 | /* Special case for the root. */ | ||
| 148 | strlcpy (cwd, "/", cwd_size); | ||
| 149 | } | ||
| 150 | |||
| 151 | return true; | ||
| 152 | } | ||
diff --git a/examples/recursor.c b/examples/recursor.c new file mode 100644 index 0000000..79c784a --- /dev/null +++ b/examples/recursor.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <syscall.h> | ||
| 4 | |||
| 5 | int | ||
| 6 | main (int argc, char *argv[]) | ||
| 7 | { | ||
| 8 | char buffer[128]; | ||
| 9 | pid_t pid; | ||
| 10 | int retval = 0; | ||
| 11 | |||
| 12 | if (argc != 4) | ||
| 13 | { | ||
| 14 | printf ("usage: recursor <string> <depth> <waitp>\n"); | ||
| 15 | exit (1); | ||
| 16 | } | ||
| 17 | |||
| 18 | /* Print args. */ | ||
| 19 | printf ("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]); | ||
| 20 | |||
| 21 | /* Execute child and wait for it to finish if requested. */ | ||
| 22 | if (atoi (argv[2]) != 0) | ||
| 23 | { | ||
| 24 | snprintf (buffer, sizeof buffer, | ||
| 25 | "recursor %s %d %s", argv[1], atoi (argv[2]) - 1, argv[3]); | ||
| 26 | pid = exec (buffer); | ||
| 27 | if (atoi (argv[3])) | ||
| 28 | retval = wait (pid); | ||
| 29 | } | ||
| 30 | |||
| 31 | /* Done. */ | ||
| 32 | printf ("%s %s: dying, retval=%d\n", argv[1], argv[2], retval); | ||
| 33 | exit (retval); | ||
| 34 | } | ||
diff --git a/examples/rm.c b/examples/rm.c new file mode 100644 index 0000000..0db7f7b --- /dev/null +++ b/examples/rm.c | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /* rm.c | ||
| 2 | |||
| 3 | Removes files specified on command line. */ | ||
| 4 | |||
| 5 | #include <stdio.h> | ||
| 6 | #include <syscall.h> | ||
| 7 | |||
| 8 | int | ||
| 9 | main (int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | bool success = true; | ||
| 12 | int i; | ||
| 13 | |||
| 14 | for (i = 1; i < argc; i++) | ||
| 15 | if (!remove (argv[i])) | ||
| 16 | { | ||
| 17 | printf ("%s: remove failed\n", argv[i]); | ||
| 18 | success = false; | ||
| 19 | } | ||
| 20 | return success ? EXIT_SUCCESS : EXIT_FAILURE; | ||
| 21 | } | ||
diff --git a/examples/shell.c b/examples/shell.c new file mode 100644 index 0000000..93641b4 --- /dev/null +++ b/examples/shell.c | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | #include <stdbool.h> | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <string.h> | ||
| 4 | #include <syscall.h> | ||
| 5 | |||
| 6 | static void read_line (char line[], size_t); | ||
| 7 | static bool backspace (char **pos, char line[]); | ||
| 8 | |||
| 9 | int | ||
| 10 | main (void) | ||
| 11 | { | ||
| 12 | printf ("Shell starting...\n"); | ||
| 13 | for (;;) | ||
| 14 | { | ||
| 15 | char command[80]; | ||
| 16 | |||
| 17 | /* Read command. */ | ||
| 18 | printf ("--"); | ||
| 19 | read_line (command, sizeof command); | ||
| 20 | |||
| 21 | /* Execute command. */ | ||
| 22 | if (!strcmp (command, "exit")) | ||
| 23 | break; | ||
| 24 | else if (!memcmp (command, "cd ", 3)) | ||
| 25 | { | ||
| 26 | if (!chdir (command + 3)) | ||
| 27 | printf ("\"%s\": chdir failed\n", command + 3); | ||
| 28 | } | ||
| 29 | else if (command[0] == '\0') | ||
| 30 | { | ||
| 31 | /* Empty command. */ | ||
| 32 | } | ||
| 33 | else | ||
| 34 | { | ||
| 35 | pid_t pid = exec (command); | ||
| 36 | if (pid != PID_ERROR) | ||
| 37 | printf ("\"%s\": exit code %d\n", command, wait (pid)); | ||
| 38 | else | ||
| 39 | printf ("exec failed\n"); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | printf ("Shell exiting."); | ||
| 44 | return EXIT_SUCCESS; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* Reads a line of input from the user into LINE, which has room | ||
| 48 | for SIZE bytes. Handles backspace and Ctrl+U in the ways | ||
| 49 | expected by Unix users. On return, LINE will always be | ||
| 50 | null-terminated and will not end in a new-line character. */ | ||
| 51 | static void | ||
| 52 | read_line (char line[], size_t size) | ||
| 53 | { | ||
| 54 | char *pos = line; | ||
| 55 | for (;;) | ||
| 56 | { | ||
| 57 | char c; | ||
| 58 | read (STDIN_FILENO, &c, 1); | ||
| 59 | |||
| 60 | switch (c) | ||
| 61 | { | ||
| 62 | case '\r': | ||
| 63 | *pos = '\0'; | ||
| 64 | putchar ('\n'); | ||
| 65 | return; | ||
| 66 | |||
| 67 | case '\b': | ||
| 68 | backspace (&pos, line); | ||
| 69 | break; | ||
| 70 | |||
| 71 | case ('U' - 'A') + 1: /* Ctrl+U. */ | ||
| 72 | while (backspace (&pos, line)) | ||
| 73 | continue; | ||
| 74 | break; | ||
| 75 | |||
| 76 | default: | ||
| 77 | /* Add character to line. */ | ||
| 78 | if (pos < line + size - 1) | ||
| 79 | { | ||
| 80 | putchar (c); | ||
| 81 | *pos++ = c; | ||
| 82 | } | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | /* If *POS is past the beginning of LINE, backs up one character | ||
| 89 | position. Returns true if successful, false if nothing was | ||
| 90 | done. */ | ||
| 91 | static bool | ||
| 92 | backspace (char **pos, char line[]) | ||
| 93 | { | ||
| 94 | if (*pos > line) | ||
| 95 | { | ||
| 96 | /* Back up cursor, overwrite character, back up | ||
| 97 | again. */ | ||
| 98 | printf ("\b \b"); | ||
| 99 | (*pos)--; | ||
| 100 | return true; | ||
| 101 | } | ||
| 102 | else | ||
| 103 | return false; | ||
| 104 | } | ||
diff --git a/examples/test.c b/examples/test.c new file mode 100644 index 0000000..44dc307 --- /dev/null +++ b/examples/test.c | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* test.c | ||
| 2 | |||
| 3 | Experiments with syscalls | ||
| 4 | argc < 2 Print Hello World | ||
| 5 | argv[1][0] == 'p' print argv[2] | ||
| 6 | == 'e' Exec Test | ||
| 7 | == 'f' File test | ||
| 8 | == 'F' File descriptor stress test | ||
| 9 | == 'h' Halt | ||
| 10 | == '0' Null-Pointer Access | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <stdio.h> | ||
| 14 | #include <syscall.h> | ||
| 15 | |||
| 16 | #define LARGE_BUF_SIZE 4150 | ||
| 17 | char large_buf[LARGE_BUF_SIZE]; | ||
| 18 | |||
| 19 | #define NUM_EXEC_CHILDS 7 | ||
| 20 | char *execs[NUM_EXEC_CHILDS] = { "test", "test p FOO", "test p BAR", "test f", "test 0", &large_buf[0], "test^" }; | ||
| 21 | |||
| 22 | #define MAX_FD 4097 | ||
| 23 | |||
| 24 | static void init_args(void); | ||
| 25 | static void init_args() | ||
| 26 | { | ||
| 27 | int i = 0; | ||
| 28 | char *t = ""; | ||
| 29 | while(i < LARGE_BUF_SIZE-1) { | ||
| 30 | if(!*t) t = "test "; | ||
| 31 | large_buf[i++] = *t++; | ||
| 32 | } | ||
| 33 | large_buf[LARGE_BUF_SIZE-1]='\0'; | ||
| 34 | } | ||
| 35 | |||
| 36 | int | ||
| 37 | main (int argc, char** argv) | ||
| 38 | { | ||
| 39 | if(argc < 2) { | ||
| 40 | printf("Hello World!\n"); | ||
| 41 | exit(0); | ||
| 42 | } | ||
| 43 | init_args(); | ||
| 44 | if(argv[1][0] == 'e') { | ||
| 45 | int r = 0; | ||
| 46 | int i; | ||
| 47 | int tid[NUM_EXEC_CHILDS]; | ||
| 48 | |||
| 49 | for(i = 0; i < NUM_EXEC_CHILDS; i++) { | ||
| 50 | tid[i] = exec(execs[i]); | ||
| 51 | } | ||
| 52 | for(i = 0; i < NUM_EXEC_CHILDS; i++) { | ||
| 53 | if (tid[i] >= 0) { | ||
| 54 | r = wait(tid[i]); | ||
| 55 | printf("P child %d exited with exit code %d\n",i, r); | ||
| 56 | } else { | ||
| 57 | printf("P child %d failed to start\n", i); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } else if(argv[1][0] == 'f') { | ||
| 61 | char buf[10]; | ||
| 62 | int r; | ||
| 63 | create ("test.txt", 10); | ||
| 64 | int handle = open ("test.txt"); | ||
| 65 | if (handle < 2) | ||
| 66 | printf ("open(test.txt) returned %d", handle); | ||
| 67 | if ((r=write(handle,"987654321",10)) != 10) { | ||
| 68 | printf("write failed: %d not %d\n",r,10); | ||
| 69 | exit(1); | ||
| 70 | } | ||
| 71 | seek(handle,0); | ||
| 72 | if ((r=read(handle, buf, 10)) != 10) { | ||
| 73 | printf("read failed: %d not %d\n",r,10); | ||
| 74 | exit(1); | ||
| 75 | } | ||
| 76 | printf("test.txt: %s\n", buf); | ||
| 77 | } else if(argv[1][0] == 'F') { | ||
| 78 | int j,i; | ||
| 79 | create ("foo.txt", 10); | ||
| 80 | for (j = 0; j < 5; j++) { | ||
| 81 | for (i = 2; i <= MAX_FD; i++) { | ||
| 82 | if (open ("foo.txt") < 0) { | ||
| 83 | printf("Opening the %d's file failed\n",i-2); | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | while(--i >= 2) { | ||
| 88 | close (i); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } else if(argv[1][0] == '0') { | ||
| 92 | printf("Null pointer value is: %d\n",*((int*)NULL)); | ||
| 93 | } else if(argv[1][0] == 'h') { | ||
| 94 | halt(); | ||
| 95 | } else if(argv[1][0] == 'p' && argc >= 3) { | ||
| 96 | printf("%s\n", argv[2]); | ||
| 97 | } else { | ||
| 98 | printf("ARGV[1] is %s\n", argv[1]); | ||
| 99 | } | ||
| 100 | return 0; | ||
| 101 | } | ||
