git home / emma home
logo

typie

Minimal typing practice tool.
git clone https://git.y1.nz/archives/typie.tar.gz
README | Files | Log | Refs | LICENSE

opt.c


      1 
      2 #include <stdlib.h>
      3 #include <stdio.h>
      4 #include <limits.h>
      5 
      6 #include "opt.h"
      7 #include "typer.h"
      8 
      9 #define ERROR(message)  fprintf(stderr, COLOR_RED message COLOR_RESET);
     10 #define ERRORARG(message, arg)\
     11 	fprintf(stderr, COLOR_RED message COLOR_RESET, arg);
     12 
     13 #define PROCESS_GROUP_SUCCESS  0
     14 #define PROCESS_GROUP_FAILURE  1
     15 #define PROCESS_GROUP_SKIP  2
     16 #define PARSE_INT_FAILURE  -1
     17 
     18 int
     19 parse_int(const char * arg)
     20 {
     21         char * endptr;
     22         int ret;
     23         ret = strtol(arg, &endptr, 10);
     24         if (* endptr != '\0' || ret > INT_MAX || ret < INT_MIN)
     25                 return PARSE_INT_FAILURE;
     26         return ret;
     27 }
     28 
     29 int
     30 get_flag(char c)
     31 {
     32 	switch (c) {
     33 	case 'l': return FLAG_LEARN_MODE;
     34 	case 'o': return FLAG_FILE;
     35 	case 't': return FLAG_TIME;
     36 	}
     37 
     38 	return 0;
     39 }
     40 
     41 int
     42 process_flag_group(State * state, const char * group, const char * next)
     43 {
     44 	int index;
     45 	char c;
     46 	int flag;
     47 
     48 	if (group[0] != '-') {
     49 		ERROR("Invalid flag format." "\n\n");
     50 		return 1;
     51 	}
     52 	
     53 	index = 1;
     54 	for (;;) {
     55 		c = group[index];
     56 
     57 		if (c == '\0')
     58 			break;
     59 
     60 		flag = get_flag(c);
     61 
     62 		if (flag == 0) {
     63 			ERRORARG("Unrecognized flag: -%c." "\n\n", c);
     64 			return PROCESS_GROUP_FAILURE;
     65 		}
     66 
     67 		if ((state->flags & flag) != 0) {
     68 			ERRORARG("Repeated flag: -%c." "\n\n", c);
     69 			return PROCESS_GROUP_FAILURE;
     70 		}
     71 
     72 		state->flags |= flag;
     73 
     74 		if (flag == FLAG_FILE) {
     75 			if (next == NULL || group[index+1] != '\0') {
     76 				ERROR("Filename must follow -f." "\n\n");
     77 				return PROCESS_GROUP_FAILURE;
     78 			}
     79 
     80 			state->outfile = next;
     81 
     82 			return PROCESS_GROUP_SKIP;
     83 		}
     84 
     85 		if (flag == FLAG_TIME) {
     86 			long int duration_seconds;
     87 			if (next == NULL || group[index+1] != '\0') {
     88 				ERROR("Integer must follow -t." "\n\n");
     89 				return PROCESS_GROUP_FAILURE;
     90 			}
     91 
     92 			duration_seconds = parse_int(next);
     93 			if (duration_seconds == PARSE_INT_FAILURE) {
     94 				ERROR("Integer must follow -t." "\n\n");
     95 				return PROCESS_GROUP_FAILURE;
     96 			}
     97 			state->duration_millis = duration_seconds * 1000;
     98 
     99 			return PROCESS_GROUP_SKIP;
    100 		}
    101 
    102 		index++;
    103 	}
    104 
    105 	return 0;
    106 }
    107 
    108 int
    109 set_flags(State * state, int argc, const char * argv[])
    110 {
    111 	int index = 1;
    112 	const char * group;
    113 	const char * next;
    114 	int result;
    115 
    116 	if (argc == 2)
    117 		return 0;
    118 
    119 	if (argc == 1) {
    120 		ERROR("Not enough arguments." "\n\n");
    121 		return 1;
    122 	}
    123 
    124 	for (;;) {
    125 		group = argv[index];
    126 		next = (index+1 < argc-1) ? argv[index+1] : NULL;
    127 
    128 		result = process_flag_group(state, group, next);
    129 		if (result == PROCESS_GROUP_SKIP)
    130 			index++;
    131 		if (result == PROCESS_GROUP_FAILURE)
    132 			return 1;
    133 	
    134 		index++;
    135 		if(index >= argc-1) /* last arg is PROMPT */
    136 			break;
    137 	}
    138 
    139 	return 0;
    140 }
    141 

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.