Compare commits
	
		
			6 Commits
		
	
	
		
			6afd2ad97b
			...
			880627f66c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 880627f66c | |||
| d625d4a99c | |||
| b063f60235 | |||
| 707db786a6 | |||
| d4a9143df6 | |||
| b7e2de196e | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					main
 | 
				
			||||||
							
								
								
									
										15
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    // Use IntelliSense to learn about possible attributes.
 | 
				
			||||||
 | 
					    // Hover to view descriptions of existing attributes.
 | 
				
			||||||
 | 
					    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
				
			||||||
 | 
					    "version": "0.2.0",
 | 
				
			||||||
 | 
					    "configurations": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "Debug main",
 | 
				
			||||||
 | 
					            "type": "cppdbg",
 | 
				
			||||||
 | 
					            "request": "launch",
 | 
				
			||||||
 | 
					            "program": "${workspaceRoot}/main",
 | 
				
			||||||
 | 
					            "cwd": "${workspaceRoot}"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								aliases.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								aliases.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					#ifndef ALIASES_H
 | 
				
			||||||
 | 
					#define ALIASES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define u8 uint8_t
 | 
				
			||||||
 | 
					#define u16 uint16_t
 | 
				
			||||||
 | 
					#define u32 uint32_t
 | 
				
			||||||
 | 
					#define u64 uint64_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define i8 int8_t
 | 
				
			||||||
 | 
					#define i16 int16_t
 | 
				
			||||||
 | 
					#define i32 int32_t
 | 
				
			||||||
 | 
					#define i64 int64_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define f32 float
 | 
				
			||||||
 | 
					#define f64 double
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define INTERNAL static
 | 
				
			||||||
 | 
					#define PERSISTENT static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					#define CLASS_MEMBER static
 | 
				
			||||||
 | 
					#endif // __cplusplus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // !ALIASES_H
 | 
				
			||||||
							
								
								
									
										229
									
								
								argparser.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								argparser.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,229 @@
 | 
				
			|||||||
 | 
					#include "argparser.h"
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define INITIAL_SIZE 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct argparser {
 | 
				
			||||||
 | 
					  arg_t *args;
 | 
				
			||||||
 | 
					  u64 size;
 | 
				
			||||||
 | 
					  u64 args_count;
 | 
				
			||||||
 | 
					  u64 positional_count;
 | 
				
			||||||
 | 
					  u64 named_count;
 | 
				
			||||||
 | 
					  u64 flag_count;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					argparser_t *create_parser(void) {
 | 
				
			||||||
 | 
					  argparser_t *parser = (argparser_t *)malloc(sizeof(argparser_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!parser) {
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  parser->args = (arg_t *)malloc(INITIAL_SIZE * sizeof(arg_t));
 | 
				
			||||||
 | 
					  if (!(parser->args)) {
 | 
				
			||||||
 | 
					    free(parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  parser->size = INITIAL_SIZE;
 | 
				
			||||||
 | 
					  parser->args_count = parser->positional_count = parser->named_count =
 | 
				
			||||||
 | 
					      parser->flag_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_FLAG, "h", "help"});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return parser;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void destroy_parser(argparser_t **parser) {
 | 
				
			||||||
 | 
					  if (*parser) {
 | 
				
			||||||
 | 
					    if ((*parser)->args) {
 | 
				
			||||||
 | 
					      free((*parser)->args);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(*parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *parser = NULL;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void add_argument(argparser_t *parser, arg_t arg) {
 | 
				
			||||||
 | 
					  bool valid_arg_type = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (arg.type) {
 | 
				
			||||||
 | 
					  case ARG_TYPE_POSITIONAL:
 | 
				
			||||||
 | 
					  case ARG_TYPE_NAMED:
 | 
				
			||||||
 | 
					  case ARG_TYPE_FLAG:
 | 
				
			||||||
 | 
					    valid_arg_type = true;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  default:
 | 
				
			||||||
 | 
					    valid_arg_type = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!valid_arg_type) {
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (parser->args_count + 1 == parser->size) {
 | 
				
			||||||
 | 
					    arg_t *new_args =
 | 
				
			||||||
 | 
					        (arg_t *)malloc((parser->size + INITIAL_SIZE) * sizeof(arg_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!new_args) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(new_args, parser->args, parser->args_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    free(parser->args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser->args = new_args;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  parser->args[(parser->args_count)++] = arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (arg.type) {
 | 
				
			||||||
 | 
					  case ARG_TYPE_POSITIONAL:
 | 
				
			||||||
 | 
					    ++(parser->positional_count);
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  case ARG_TYPE_NAMED:
 | 
				
			||||||
 | 
					    ++(parser->named_count);
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  case ARG_TYPE_FLAG:
 | 
				
			||||||
 | 
					    ++(parser->flag_count);
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  default:
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void print_usage(argparser_t *parser) {
 | 
				
			||||||
 | 
					  arg_t positional[parser->positional_count];
 | 
				
			||||||
 | 
					  memset(positional, 0, parser->positional_count);
 | 
				
			||||||
 | 
					  u64 positional_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  arg_t named[parser->named_count];
 | 
				
			||||||
 | 
					  memset(named, 0, parser->named_count);
 | 
				
			||||||
 | 
					  u64 named_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  arg_t flag[parser->flag_count];
 | 
				
			||||||
 | 
					  memset(flag, 0, parser->flag_count);
 | 
				
			||||||
 | 
					  u64 flag_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < parser->args_count; ++i) {
 | 
				
			||||||
 | 
					    const arg_t *arg = &(parser->args[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (arg->type) {
 | 
				
			||||||
 | 
					    case ARG_TYPE_POSITIONAL:
 | 
				
			||||||
 | 
					      positional[positional_index++] = *arg;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ARG_TYPE_NAMED:
 | 
				
			||||||
 | 
					      named[named_index++] = *arg;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case ARG_TYPE_FLAG:
 | 
				
			||||||
 | 
					      flag[flag_index++] = *arg;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  char usage_line[2048] = {0};
 | 
				
			||||||
 | 
					  char positional_args[2048] = {0};
 | 
				
			||||||
 | 
					  char named_args[2048] = {0};
 | 
				
			||||||
 | 
					  char flag_args[2048] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sprintf(usage_line, "Usage: program ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (positional_index > 0) {
 | 
				
			||||||
 | 
					    sprintf(positional_args, "Positional arguments:\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (named_index > 0) {
 | 
				
			||||||
 | 
					    sprintf(named_args, "Named arguments:\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (flag_index > 0) {
 | 
				
			||||||
 | 
					    sprintf(flag_args, "Flag arguments:\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < flag_index; ++i) {
 | 
				
			||||||
 | 
					    const arg_t *arg = &(flag[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(usage_line[strlen(usage_line)]), "[");
 | 
				
			||||||
 | 
					    sprintf(&(flag_args[strlen(flag_args)]), "\t");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (strlen(arg->short_name) > 0) {
 | 
				
			||||||
 | 
					      sprintf(&(usage_line[strlen(usage_line)]), "-%s | ", arg->short_name);
 | 
				
			||||||
 | 
					      sprintf(&(flag_args[strlen(flag_args)]), "-%s, ", arg->short_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(usage_line[strlen(usage_line)]), "--%s] ", arg->long_name);
 | 
				
			||||||
 | 
					    sprintf(&(flag_args[strlen(flag_args)]), "--%s\n", arg->long_name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < named_index; ++i) {
 | 
				
			||||||
 | 
					    const arg_t *arg = &(named[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(usage_line[strlen(usage_line)]), "[");
 | 
				
			||||||
 | 
					    sprintf(&(named_args[strlen(named_args)]), "\t");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (strlen(arg->short_name) > 0) {
 | 
				
			||||||
 | 
					      sprintf(&(usage_line[strlen(usage_line)]), "-%s | ", arg->short_name);
 | 
				
			||||||
 | 
					      sprintf(&(named_args[strlen(named_args)]), "-%s, ", arg->short_name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 name_length = strlen(arg->long_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char capitalised[name_length];
 | 
				
			||||||
 | 
					    memset(capitalised, 0, name_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strcpy(capitalised, arg->long_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u64 i = 0; i < name_length; ++i) {
 | 
				
			||||||
 | 
					      capitalised[i] = toupper(capitalised[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(usage_line[strlen(usage_line)]), "--%s %s] ", arg->long_name,
 | 
				
			||||||
 | 
					            capitalised);
 | 
				
			||||||
 | 
					    sprintf(&(named_args[strlen(named_args)]), "--%s\n", arg->long_name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (u64 i = 0; i < positional_index; ++i) {
 | 
				
			||||||
 | 
					    const arg_t *arg = &(named[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(positional_args[strlen(positional_args)]), "\t");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 name_length = strlen(arg->long_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char capitalised[name_length];
 | 
				
			||||||
 | 
					    memset(capitalised, 0, name_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    strcpy(capitalised, arg->long_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u64 i = 0; i < name_length; ++i) {
 | 
				
			||||||
 | 
					      capitalised[i] = toupper(capitalised[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sprintf(&(usage_line[strlen(usage_line)]), "%s ", capitalised);
 | 
				
			||||||
 | 
					    sprintf(&(positional_args[strlen(positional_args)]), "%s\n", capitalised);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  printf("%s\n\n", usage_line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (strlen(positional_args) > 0) {
 | 
				
			||||||
 | 
					    printf("%s\n", positional_args);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (strlen(named_args) > 0) {
 | 
				
			||||||
 | 
					    printf("%s\n", named_args);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (strlen(flag_args) > 0) {
 | 
				
			||||||
 | 
					    printf("%s\n", flag_args);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								argparser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								argparser.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#ifndef ARGPARSER_H
 | 
				
			||||||
 | 
					#define ARGPARSER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct argparser argparser_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					  ARG_TYPE_POSITIONAL,
 | 
				
			||||||
 | 
					  ARG_TYPE_NAMED,
 | 
				
			||||||
 | 
					  ARG_TYPE_FLAG,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  COUNT_ARG_TYPE,
 | 
				
			||||||
 | 
					} arg_type_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					  arg_type_t type;
 | 
				
			||||||
 | 
					  const char *short_name;
 | 
				
			||||||
 | 
					  const char *long_name;
 | 
				
			||||||
 | 
					} arg_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					argparser_t *create_parser(void);
 | 
				
			||||||
 | 
					void destroy_parser(argparser_t **parser);
 | 
				
			||||||
 | 
					void add_argument(argparser_t *parser, arg_t arg);
 | 
				
			||||||
 | 
					void print_usage(argparser_t *parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // !ARGPARSER_H
 | 
				
			||||||
							
								
								
									
										4
									
								
								build
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								build
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
				
			|||||||
#!/usr/bin/bash
 | 
					#!/usr/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CC=clang++
 | 
					CC=clang
 | 
				
			||||||
CFLAGS="-g -Wall -Werror -pedantic"
 | 
					CFLAGS="-g -Wall -Werror -pedantic"
 | 
				
			||||||
SRC=*.cpp
 | 
					SRC=*.c
 | 
				
			||||||
OUT=main
 | 
					OUT=main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set -x
 | 
					set -x
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					#include "argparser.h"
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
 | 
					  argparser_t *parser = create_parser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "c", "count"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "g", "group"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_NAMED, "t", "test"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_NAMED, "f", "fault"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_NAMED, "e", "emblem"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_FLAG, "u", "undo"});
 | 
				
			||||||
 | 
					  add_argument(parser, (arg_t){ARG_TYPE_FLAG, "d", "delete"});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  print_usage(parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  destroy_parser(&parser);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user