getting fancy with command line args
This commit is contained in:
103
src/args.c
Normal file
103
src/args.c
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include "args.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void print_usage(const char *program_name) {
|
||||||
|
printf("Usage: %s [OPTIONS]\n", program_name);
|
||||||
|
printf("Calculate the church calendar for the current year.\n\n");
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" --all Print all days in the current liturgical year\n");
|
||||||
|
printf(" --date MM-DD-YYYY Print the liturgical day for the specified date\n");
|
||||||
|
printf(" --year YYYY Print all days in the specified year\n");
|
||||||
|
printf(" --help Display this help message\n");
|
||||||
|
printf("\nWith no options, prints only today's liturgical day.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_date(const char *date_str, struct tm *date) {
|
||||||
|
int month, day, year;
|
||||||
|
|
||||||
|
if (sscanf(date_str, "%d-%d-%d", &month, &day, &year) != 3) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate ranges
|
||||||
|
if (month < 1 || month > 12 || day < 1 || day > 31 || year < 1900 || year > 9999) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(date, 0, sizeof(struct tm));
|
||||||
|
date->tm_mon = month - 1;
|
||||||
|
date->tm_mday = day;
|
||||||
|
date->tm_year = year - 1900;
|
||||||
|
|
||||||
|
// Normalize the date
|
||||||
|
if (mktime(date) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_args(int argc, char *argv[], ProgramArgs *args) {
|
||||||
|
// Initialize with defaults
|
||||||
|
args->mode = MODE_TODAY;
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm *today = localtime(&now);
|
||||||
|
args->target_date = *today;
|
||||||
|
args->target_year = today->tm_year + 1900;
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "--help") == 0) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
} else if (strcmp(argv[i], "--all") == 0) {
|
||||||
|
args->mode = MODE_ALL;
|
||||||
|
} else if (strcmp(argv[i], "--date") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "Error: --date requires a date argument (MM-DD-YYYY)\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse_date(argv[i + 1], &args->target_date) != 0) {
|
||||||
|
fprintf(stderr, "Error: Invalid date format '%s'. Use MM-DD-YYYY\n", argv[i + 1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
args->mode = MODE_DATE;
|
||||||
|
args->target_year = args->target_date.tm_year + 1900;
|
||||||
|
i++; // Skip the date argument
|
||||||
|
} else if (strcmp(argv[i], "--year") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "Error: --year requires a year argument\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *endptr;
|
||||||
|
long year = strtol(argv[i + 1], &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr != '\0' || year < 1900 || year > 9999) {
|
||||||
|
fprintf(stderr, "Error: Invalid year '%s'\n", argv[i + 1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
args->mode = MODE_YEAR;
|
||||||
|
args->target_year = (int)year;
|
||||||
|
|
||||||
|
// Set target_date to January 1 of that year for calendar generation
|
||||||
|
memset(&args->target_date, 0, sizeof(struct tm));
|
||||||
|
args->target_date.tm_year = (int)(year - 1900);
|
||||||
|
args->target_date.tm_mon = 0;
|
||||||
|
args->target_date.tm_mday = 1;
|
||||||
|
mktime(&args->target_date);
|
||||||
|
|
||||||
|
i++; // Skip the year argument
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
26
src/args.h
Normal file
26
src/args.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef ARGS_H
|
||||||
|
#define ARGS_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MODE_TODAY,
|
||||||
|
MODE_ALL,
|
||||||
|
MODE_DATE,
|
||||||
|
MODE_YEAR
|
||||||
|
} OutputMode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OutputMode mode;
|
||||||
|
struct tm target_date;
|
||||||
|
int target_year;
|
||||||
|
} ProgramArgs;
|
||||||
|
|
||||||
|
// Parse command line arguments
|
||||||
|
// Returns 0 on success, -1 on error, 1 if help was shown
|
||||||
|
int parse_args(int argc, char *argv[], ProgramArgs *args);
|
||||||
|
|
||||||
|
// Print usage information
|
||||||
|
void print_usage(const char *program_name);
|
||||||
|
|
||||||
|
#endif // ARGS_H
|
||||||
82
src/main.c
82
src/main.c
@@ -1,17 +1,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "church_day.h"
|
#include "church_day.h"
|
||||||
#include "builder.h"
|
#include "builder.h"
|
||||||
|
#include "args.h"
|
||||||
static void print_usage(const char *program_name) {
|
|
||||||
printf("Usage: %s [OPTIONS]\n", program_name);
|
|
||||||
printf("Calculate the church calendar for the current year.\n\n");
|
|
||||||
printf("Options:\n");
|
|
||||||
printf(" --all Print all days in the liturgical year\n");
|
|
||||||
printf(" --help Display this help message\n");
|
|
||||||
printf("\nWith no options, prints only today's liturgical day.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int compare_dates(struct tm d1, struct tm d2) {
|
static int compare_dates(struct tm d1, struct tm d2) {
|
||||||
if (d1.tm_year != d2.tm_year) return d1.tm_year - d2.tm_year;
|
if (d1.tm_year != d2.tm_year) return d1.tm_year - d2.tm_year;
|
||||||
@@ -19,32 +10,7 @@ static int compare_dates(struct tm d1, struct tm d2) {
|
|||||||
return d1.tm_mday - d2.tm_mday;
|
return d1.tm_mday - d2.tm_mday;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
static void print_day(const ChurchDay *day) {
|
||||||
int print_all = 0;
|
|
||||||
|
|
||||||
// Parse arguments
|
|
||||||
for (int i = 1; i < argc; i++) {
|
|
||||||
if (strcmp(argv[i], "--all") == 0) {
|
|
||||||
print_all = 1;
|
|
||||||
} else if (strcmp(argv[i], "--help") == 0) {
|
|
||||||
print_usage(argv[0]);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
|
||||||
print_usage(argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time_t now = time(NULL);
|
|
||||||
struct tm *today = localtime(&now);
|
|
||||||
|
|
||||||
ChurchYear seasons = proper_of_seasons(*today);
|
|
||||||
|
|
||||||
if (print_all) {
|
|
||||||
// Print all days
|
|
||||||
for (size_t i = 0; i < seasons.count; i++) {
|
|
||||||
ChurchDay *day = &seasons.days[i];
|
|
||||||
printf("%s, %s %d, %d - %s - %s in %s\n",
|
printf("%s, %s %d, %d - %s - %s in %s\n",
|
||||||
church_day_weekday_string(day),
|
church_day_weekday_string(day),
|
||||||
church_day_month_name(day),
|
church_day_month_name(day),
|
||||||
@@ -54,30 +20,50 @@ int main(int argc, char *argv[]) {
|
|||||||
day_class_to_string(day->class),
|
day_class_to_string(day->class),
|
||||||
season_to_string(day->season));
|
season_to_string(day->season));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Print only today
|
int main(int argc, char *argv[]) {
|
||||||
|
ProgramArgs args;
|
||||||
|
int parse_result = parse_args(argc, argv, &args);
|
||||||
|
|
||||||
|
if (parse_result == 1) {
|
||||||
|
// Help was shown
|
||||||
|
return 0;
|
||||||
|
} else if (parse_result == -1) {
|
||||||
|
// Error occurred
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChurchYear seasons = proper_of_seasons(args.target_date);
|
||||||
|
|
||||||
|
switch (args.mode) {
|
||||||
|
case MODE_ALL:
|
||||||
|
case MODE_YEAR:
|
||||||
|
// Print all days
|
||||||
|
for (size_t i = 0; i < seasons.count; i++) {
|
||||||
|
print_day(&seasons.days[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MODE_TODAY:
|
||||||
|
case MODE_DATE: {
|
||||||
|
// Print only the specified day
|
||||||
ChurchDay *found = NULL;
|
ChurchDay *found = NULL;
|
||||||
for (size_t i = 0; i < seasons.count; i++) {
|
for (size_t i = 0; i < seasons.count; i++) {
|
||||||
if (compare_dates(seasons.days[i].date, *today) == 0) {
|
if (compare_dates(seasons.days[i].date, args.target_date) == 0) {
|
||||||
found = &seasons.days[i];
|
found = &seasons.days[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
printf("%s, %s %d, %d - %s - %s in %s\n",
|
print_day(found);
|
||||||
church_day_weekday_string(found),
|
|
||||||
church_day_month_name(found),
|
|
||||||
found->date.tm_mday,
|
|
||||||
found->date.tm_year + 1900,
|
|
||||||
found->description,
|
|
||||||
day_class_to_string(found->class),
|
|
||||||
season_to_string(found->season));
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Could not find today's date in the liturgical calendar.\n");
|
fprintf(stderr, "Could not find the specified date in the liturgical calendar.\n");
|
||||||
church_year_free(&seasons);
|
church_year_free(&seasons);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
church_year_free(&seasons);
|
church_year_free(&seasons);
|
||||||
|
|||||||
Reference in New Issue
Block a user