Browse Source

Add getopt, getopt_long

K. Lange 2 years ago
parent
commit
b4c1d997b4
15 changed files with 231 additions and 148 deletions
  1. 2 40
      apps/compositor.c
  2. 16 22
      apps/free.c
  3. 1 1
      apps/init.c
  4. 2 2
      apps/julia.c
  5. 1 30
      apps/ls.c
  6. 3 3
      apps/migrate.c
  7. 2 3
      apps/nyancat.c
  8. 1 17
      apps/sh.c
  9. 2 13
      apps/terminal-vga.c
  10. 29 16
      apps/terminal.c
  11. 0 1
      apps/yutani-query.c
  12. 16 0
      base/usr/include/getopt.h
  13. 4 0
      base/usr/include/unistd.h
  14. 11 0
      libc/unistd/getopt.c
  15. 141 0
      libc/unistd/getopt_long.c

+ 2 - 40
apps/compositor.c

@@ -93,46 +93,8 @@ static int usage(char * argv[]) {
  * Parse arguments
  */
 static int parse_args(int argc, char * argv[], int * out) {
-	*out = 1;
-	for (int i = 1; i < argc; ++i) {
-		if (argv[i][0] == '-') {
-			char *c = &argv[i][1];
-			*out = *out + 1;
-			while (*c) {
-				switch (*c) {
-					case 'n':
-						yutani_options.nested = 1;
-						break;
-					case 'g':
-						{
-							char * c = strstr(argv[i+1], "x");
-							if (c) {
-								*c = '\0';
-								c++;
-								yutani_options.nest_width  = atoi(argv[i+1]);
-								yutani_options.nest_height = atoi(c);
-							}
-							i += 2;
-							goto _next;
-						}
-					case 'h':
-						return usage(argv);
-					case '-':
-						// hm
-						return 0;
-					default:
-						fprintf(stderr, "Unrecognized option: %c\n", *c);
-						break;
-				}
-				c++;
-			}
-		}
-_next:
-		;
-	}
-#if 0
 	static struct option long_opts[] = {
-		{"nest",       no_argument,       0, 'n'},
+		{"nested",     no_argument,       0, 'n'},
 		{"geometry",   required_argument, 0, 'g'},
 		{"help",       no_argument,       0, 'h'},
 		{0,0,0,0}
@@ -168,7 +130,6 @@ _next:
 		}
 	}
 	*out = optind;
-#endif
 	return 0;
 }
 
@@ -2067,6 +2028,7 @@ int main(int argc, char * argv[]) {
 								yg->resize_on_next = 1;
 							}
 							break;
+						case YUTANI_MSG_WINDOW_CLOSE:
 						case YUTANI_MSG_SESSION_END:
 							{
 								TRACE("Host session ended. Should exit.");

+ 16 - 22
apps/free.c

@@ -7,6 +7,7 @@
  */
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 void show_usage(int argc, char * argv[]) {
 	printf(
@@ -27,28 +28,21 @@ int main(int argc, char * argv[]) {
 	int use_kilobytes = 0;
 	int show_total = 0;
 
-	if (argc > 1) {
-		for (int i = 1; i < argc; ++i) {
-			if (argv[i][0] == '-') {
-				char *c = &argv[i][1];
-				while (*c) {
-					switch (*c) {
-						case 'u':
-							show_used = 1;
-							break;
-						case 't':
-							show_total = 1;
-							break;
-						case 'k':
-							use_kilobytes = 1;
-							break;
-						case '?':
-							show_usage(argc, argv);
-							return 0;
-					}
-					c++;
-				}
-			}
+	int c;
+	while ((c = getopt(argc, argv, "utk?")) != -1) {
+		switch (c) {
+			case 'u':
+				show_used = 1;
+				break;
+			case 't':
+				show_total = 1;
+				break;
+			case 'k':
+				use_kilobytes = 1;
+				break;
+			case '?':
+				show_usage(argc, argv);
+				return 0;
 		}
 	}
 

+ 1 - 1
apps/init.c

@@ -47,7 +47,7 @@ int main(int argc, char * argv[]) {
 
 	if (argc > 1) {
 		if (!strcmp(argv[1], "--vga")) {
-			return start_options((char *[]){"/bin/terminal-vga","-l",NULL});
+			return start_options((char *[]){"/bin/terminal-vga",NULL});
 		} else if (!strcmp(argv[1], "--migrate")) {
 			return start_options((char *[]){"/bin/migrate",NULL});
 		} else {

+ 2 - 2
apps/julia.c

@@ -188,7 +188,6 @@ void resize_finish(int w, int h) {
 
 int main(int argc, char * argv[]) {
 
-#if 0
 	static struct option long_opts[] = {
 		{"no-repeat", no_argument,    0, 'n'},
 		{"initer", required_argument, 0, 'i'},
@@ -215,6 +214,7 @@ int main(int argc, char * argv[]) {
 				case 'n':
 					no_repeat = 1;
 					break;
+#if 0
 				case 'i':
 					initer = atof(optarg);
 					break;
@@ -230,6 +230,7 @@ int main(int argc, char * argv[]) {
 				case 'C':
 					cony = atof(optarg);
 					break;
+#endif
 				case 'W':
 					width = atoi(optarg);
 					break;
@@ -245,7 +246,6 @@ int main(int argc, char * argv[]) {
 			}
 		}
 	}
-#endif
 
 	yctx = yutani_init();
 	init_decorations();

+ 1 - 30
apps/ls.c

@@ -365,9 +365,8 @@ int main (int argc, char * argv[]) {
 	/* Parse arguments */
 	char * p = ".";
 
-#if 0
 	if (argc > 1) {
-		int index, c;
+		int c;
 		while ((c = getopt(argc, argv, "ahl?")) != -1) {
 			switch (c) {
 				case 'a':
@@ -384,34 +383,6 @@ int main (int argc, char * argv[]) {
 					return 0;
 			}
 		}
-#else
-	int optind = 1;
-	for (int i = 1; i < argc; ++i) {
-		if (argv[i][0] == '-') {
-			char *c = &argv[i][1];
-			optind++;
-			while (*c) {
-				switch (*c) {
-					case 'a':
-						show_hidden = 1;
-						break;
-					case 'h':
-						human_readable = 1;
-						break;
-					case 'l':
-						long_mode = 1;
-						break;
-					case '?':
-						show_usage(argc, argv);
-						return 0;
-				}
-				c++;
-			}
-		}
-	}
-
-	{
-#endif
 
 		if (optind < argc) {
 			p = argv[optind];

+ 3 - 3
apps/migrate.c

@@ -210,11 +210,11 @@ int main(int argc, char * argv[]) {
 
 	TRACE("Launching intended startup app...");
 	if (!strcmp(start, "--vga")) {
-		execvp("/bin/terminal-vga", (char *[]){"terminal-vga","-l",NULL});
+		execvp("/bin/terminal-vga", (char *[]){"terminal-vga",NULL});
 	} else if (start) {
-		execvp("/bin/compositor", (char *[]){"comositor","--",start,NULL});
+		execvp("/bin/compositor", (char *[]){"compositor","--",start,NULL});
 	} else {
-		execvp("/bin/compositor", (char *[]){"comositor",NULL});
+		execvp("/bin/compositor", (char *[]){"compositor",NULL});
 	}
 
 	return 0;

+ 2 - 3
apps/nyancat.c

@@ -364,9 +364,8 @@ int main(int argc, char ** argv) {
 
 	/* Whether or not to show the MOTD intro */
 	char show_intro = 0;
-	//char skip_intro = 0;
+	char skip_intro = 0;
 
-#if 0
 	/* Long option names */
 	static struct option long_opts[] = {
 		{"help",       no_argument,       0, 'h'},
@@ -444,8 +443,8 @@ int main(int argc, char ** argv) {
 				break;
 		}
 	}
-#endif
 
+	(void)skip_intro;
 #if 0
 	if (telnet) {
 		/* Telnet mode */

+ 1 - 17
apps/sh.c

@@ -826,23 +826,8 @@ int main(int argc, char ** argv) {
 	//add_path_contents("/usr/bin");
 	sort_commands();
 
-	for (int i = 1; i < argc; ++i) {
-		if (!strcmp(argv[i], "-c")) {
-			return shell_exec(argv[i+1]);
-		}
-		if (!strcmp(argv[i], "-v")) {
-			show_version();
-			return 0;
-		}
-		if (!strcmp(argv[i], "-?")) {
-			show_usage(argc, argv);
-			return 0;
-		}
-	}
-
-#if 0
 	if (argc > 1) {
-		int index, c;
+		int c;
 		while ((c = getopt(argc, argv, "c:v?")) != -1) {
 			switch (c) {
 				case 'c':
@@ -857,7 +842,6 @@ int main(int argc, char ** argv) {
 			}
 		}
 	}
-#endif
 
 	shell_interactive = 1;
 

+ 2 - 13
apps/terminal-vga.c

@@ -784,7 +784,6 @@ int main(int argc, char ** argv) {
 
 	_login_shell = 0;
 
-#if 0
 	static struct option long_opts[] = {
 		{"login",      no_argument,       0, 'l'},
 		{"help",       no_argument,       0, 'h'},
@@ -794,11 +793,6 @@ int main(int argc, char ** argv) {
 	/* Read some arguments */
 	int index, c;
 	while ((c = getopt_long(argc, argv, "hl", long_opts, &index)) != -1) {
-		if (!c) {
-			if (long_opts[index].flag == 0) {
-				c = long_opts[index].val;
-			}
-		}
 		switch (c) {
 			case 'l':
 				_login_shell = 1;
@@ -814,8 +808,7 @@ int main(int argc, char ** argv) {
 		}
 	}
 
-	putenv("TERM=toaru");
-#endif
+	//putenv("TERM=toaru");
 
 #if 1
 	char * _env = malloc(strlen("TERM=toaru"));
@@ -865,13 +858,11 @@ int main(int argc, char ** argv) {
 		dup2(fd_slave, 1);
 		dup2(fd_slave, 2);
 
-#if 0
 		if (argv[optind] != NULL) {
 			char * tokens[] = {argv[optind], NULL};
-			int i = execvp(tokens[0], tokens);
+			execvp(tokens[0], tokens);
 			fprintf(stderr, "Failed to launch requested startup application.\n");
 		} else {
-#endif
 			if (_login_shell) {
 				char * tokens[] = {"/bin/login",NULL};
 				execvp(tokens[0], tokens);
@@ -883,9 +874,7 @@ int main(int argc, char ** argv) {
 				execvp(tokens[0], tokens);
 				exit(1);
 			}
-#if 0
 		}
-#endif
 
 		exit_application = 1;
 

+ 29 - 16
apps/terminal.c

@@ -538,14 +538,27 @@ term_write_char(
 #endif
 	}
 _extra_stuff:
-	if (flags & ANSI_UNDERLINE) {
-		for (uint8_t i = 0; i < char_width; ++i) {
-			term_set_point(x + i, y + char_offset + 2, _fg);
+	if (_use_freetype) {
+		if (flags & ANSI_UNDERLINE) {
+			for (uint8_t i = 0; i < char_width; ++i) {
+				term_set_point(x + i, y + char_offset + 2, _fg);
+			}
 		}
-	}
-	if (flags & ANSI_CROSS) {
-		for (uint8_t i = 0; i < char_width; ++i) {
-			term_set_point(x + i, y + char_offset - 5, _fg);
+		if (flags & ANSI_CROSS) {
+			for (uint8_t i = 0; i < char_width; ++i) {
+				term_set_point(x + i, y + char_offset - 5, _fg);
+			}
+		}
+	} else {
+		if (flags & ANSI_UNDERLINE) {
+			for (uint8_t i = 0; i < char_width; ++i) {
+				term_set_point(x + i, y + char_height - 1, _fg);
+			}
+		}
+		if (flags & ANSI_CROSS) {
+			for (uint8_t i = 0; i < char_width; ++i) {
+				term_set_point(x + i, y + char_height - 7, _fg);
+			}
 		}
 	}
 	if (flags & ANSI_BORDER) {
@@ -1292,9 +1305,11 @@ void usage(char * argv[]) {
 			"usage: %s [-b] [-F] [-h]\n"
 			"\n"
 			" -F --fullscreen \033[3mRun in fullscreen (background) mode.\033[0m\n"
+#if 0
 			" -b --bitmap     \033[3mUse the integrated bitmap font.\033[0m\n"
-			" -h --help       \033[3mShow this help message.\033[0m\n"
 			" -s --scale      \033[3mScale the font in FreeType mode by a given amount.\033[0m\n"
+#endif
+			" -h --help       \033[3mShow this help message.\033[0m\n"
 			" -x --grid       \033[3mMake resizes round to nearest match for character cell size.\033[0m\n"
 			" -n --no-frame   \033[3mDisable decorations.\033[0m\n"
 			"\n"
@@ -1598,16 +1613,17 @@ int main(int argc, char ** argv) {
 	window_width  = char_width * 80;
 	window_height = char_height * 24;
 
-#if 0
 	static struct option long_opts[] = {
 		{"fullscreen", no_argument,       0, 'F'},
+#if 0
 		{"bitmap",     no_argument,       0, 'b'},
+		{"scale",      required_argument, 0, 's'},
+#endif
 		{"login",      no_argument,       0, 'l'},
 		{"help",       no_argument,       0, 'h'},
 		{"kernel",     no_argument,       0, 'k'},
 		{"grid",       no_argument,       0, 'x'},
 		{"no-frame",   no_argument,       0, 'n'},
-		{"scale",      required_argument, 0, 's'},
 		{"geometry",   required_argument, 0, 'g'},
 		{0,0,0,0}
 	};
@@ -1644,10 +1660,12 @@ int main(int argc, char ** argv) {
 				usage(argv);
 				return 0;
 				break;
+#if 0
 			case 's':
 				scale_fonts = 1;
 				font_scaling = atof(optarg);
 				break;
+#endif
 			case 'g':
 				{
 					char * c = strstr(optarg, "x");
@@ -1665,7 +1683,6 @@ int main(int argc, char ** argv) {
 				break;
 		}
 	}
-#endif
 
 	// XXX
 	//putenv("TERM=toaru");
@@ -1771,13 +1788,11 @@ int main(int argc, char ** argv) {
 		dup2(fd_slave, 1);
 		dup2(fd_slave, 2);
 
-#if 0
 		if (argv[optind] != NULL) {
 			char * tokens[] = {argv[optind], NULL};
-			int i = execvp(tokens[0], tokens);
+			execvp(tokens[0], tokens);
 			fprintf(stderr, "Failed to launch requested startup application.\n");
 		} else {
-#endif
 			if (_login_shell) {
 				char * tokens[] = {"/bin/login",NULL};
 				execvp(tokens[0], tokens);
@@ -1789,9 +1804,7 @@ int main(int argc, char ** argv) {
 				execvp(tokens[0], tokens);
 				exit(1);
 			}
-#if 0
 		}
-#endif
 
 		exit_application = 1;
 

+ 0 - 1
apps/yutani-query.c

@@ -1,5 +1,4 @@
 #include <stdio.h>
-#include <getopt.h>
 
 #include <toaru/yutani.h>
 

+ 16 - 0
base/usr/include/getopt.h

@@ -1 +1,17 @@
 #pragma once
+
+struct option {
+    const char *name;
+    int has_arg;
+    int *flag;
+    int val;
+};
+
+extern char * optarg;
+extern int optind, opterr, optopt;
+
+extern int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2 /* Unsupported */

+ 4 - 0
base/usr/include/unistd.h

@@ -45,6 +45,10 @@ extern off_t lseek(int fd, off_t offset, int whence);
 
 extern int access(const char * pathname, int mode);
 
+extern int getopt(int argc, char * const argv[], const char * optstring);
+
+extern char * optarg;
+extern int optind, opterr, optopt;
 
 #define STDIN_FILENO 0
 #define STDOUT_FILENO 1

+ 11 - 0
libc/unistd/getopt.c

@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <getopt.h>
+
+char * optarg = NULL;
+int optind = 1;
+int opterr = 1;
+int optopt = 0;
+
+int getopt(int argc, char * const argv[], const char * optstring) {
+	return getopt_long(argc, argv, optstring, NULL, 0);
+}

+ 141 - 0
libc/unistd/getopt_long.c

@@ -0,0 +1,141 @@
+#include <unistd.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+
+/**
+ * getopt / getopt_long
+ */
+
+int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) {
+	static char * nextchar = NULL;
+
+	if (optind >= argc) {
+		return -1;
+	}
+
+	do {
+		if (!nextchar) {
+			nextchar = argv[optind];
+			if (*nextchar != '-') {
+				return -1;
+			} else {
+				nextchar++;
+
+				if (*nextchar == '\0') {
+					/* Special case - is a non-option argument */
+					return -1;
+				}
+
+				if (*nextchar == '-') {
+					if (nextchar[1] == '\0') {
+						/* End of arguments */
+						optind++;
+						return -1;
+					} else {
+						if (!longopts) {
+							optind++;
+							return -1;
+						}
+						/* Scan through options */
+						nextchar++;
+						char tmp[strlen(nextchar)+1];
+						strcpy(tmp, nextchar);
+						char * eq = strchr(tmp, '=');
+						if (eq) {
+							*eq = '\0';
+							optarg = nextchar + (eq - tmp + 1);
+						} else {
+							optarg = NULL;
+						}
+
+						int found = -1;
+						for (int index = 0; longopts[index].name; ++index) {
+							if (!strcmp(longopts[index].name, tmp)) {
+								found = index;
+							}
+						}
+
+						if (found == -1) {
+							if (longindex) {
+								*longindex = -1;
+							}
+							if (opterr) {
+								fprintf(stderr, "unknown long argument: %s\n", tmp);
+							}
+							nextchar = NULL;
+							optind++;
+							optopt = '\0';
+							return '?';
+						} else {
+							if (longindex) {
+								*longindex = found;
+							}
+							if (longopts[found].has_arg == required_argument) {
+								if (!optarg) {
+									optarg = argv[optind+1];
+									optind++;
+								}
+							}
+							nextchar = NULL;
+							optind++;
+							if (!longopts[found].flag) {
+								return longopts[found].val;
+							} else {
+								*longopts[found].flag = longopts[found].val;
+								return 0;
+							}
+						}
+					}
+				}
+			}
+		}
+
+		if (*nextchar == '\0') {
+			nextchar = NULL;
+			optind++;
+			continue;
+		}
+
+		if ((*nextchar < 'A' || *nextchar > 'z' || (*nextchar > 'Z' && *nextchar < 'a')) && (*nextchar != '?')) {
+			if (opterr) {
+				fprintf(stderr, "Invalid option character: %c\n", *nextchar);
+			}
+			optopt = *nextchar;
+			nextchar++;
+			return '?';
+		}
+
+		char * opt = strchr(optstring, *nextchar);
+
+		if (!opt) {
+			if (opterr) {
+				fprintf(stderr, "Invalid option character: %c\n", *nextchar);
+			}
+			optopt = *nextchar;
+			nextchar++;
+			return '?';
+		}
+
+		int optout = *nextchar;
+
+		if (opt[1] == ':') {
+			if (nextchar[1] != '\0') {
+				optarg = &nextchar[1];
+				nextchar = NULL;
+				optind++;
+			} else {
+				optarg = argv[optind+1];
+				optind += 2;
+				nextchar = NULL;
+			}
+		} else {
+			nextchar++;
+		}
+
+		return optout;
+
+	} while (optind < argc);
+
+	return -1;
+}