backlog of changes from the uconsole
This commit is contained in:
parent
55bb27a1de
commit
9846c7ad27
@ -15,6 +15,7 @@
|
||||
* nybbles 4--|4--|4--|4--|4--|4--|
|
||||
* bits 111111111111111111111111 */
|
||||
|
||||
#include <complex.h>
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
/* C99 type definitions */
|
||||
# include <stdint.h>
|
||||
@ -42,6 +43,7 @@ struct Intel4004_State {
|
||||
Nybble acc; /* Accumulator */
|
||||
Nybble reg[16]; /* R0 through RF */
|
||||
Word pc[4]; /* PC0 through PC3 */
|
||||
Word *cc; /* Current PC */
|
||||
Byte *rom;
|
||||
Byte *ram;
|
||||
};
|
||||
@ -117,11 +119,38 @@ enum Intel4004_Instruction {
|
||||
/* INVALID 0xFF 0b 1111 1111 */
|
||||
};
|
||||
|
||||
#define INTEL4004_THIS_OP (state->rom[*state->cc])
|
||||
#define INTEL4004_NEXT_OP (state->rom[*state->cc + 1])
|
||||
#define INTEL4004_INC_OP do{ ++*state->cc; }while(0)
|
||||
#define INTEL4004_INC2_OP do{ *state->cc += 2; }while(0)
|
||||
|
||||
/* <http://e4004.szyc.org/>-style naming */
|
||||
#define INTEL4004_PL (*state->cc & 0x00F)
|
||||
#define INTEL4004_PM ((*state->cc & 0x0F0) >> 4)
|
||||
#define INTEL4004_PH ((*state->cc & 0xF00) >> 8)
|
||||
|
||||
/* Also see the Intel MCS-4 Assembly Language Programming Manual (1973). */
|
||||
|
||||
/* From the datasheet. */
|
||||
void Intel4004_RESET(struct Intel4004_State *state){
|
||||
Nybble i;
|
||||
|
||||
state->carry = 0;
|
||||
state->test = 0;
|
||||
state->acc = 0;
|
||||
for(i = 0; i <= (sizeof state->reg) / (sizeof *state->reg); ++i)
|
||||
state->reg[i] = 0;
|
||||
for(i = 0; i <= (sizeof state->pc) / (sizeof *state->pc); ++i)
|
||||
state->pc[i] = 0;
|
||||
state->cc = &state->pc[0];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Does nothing. */
|
||||
void Intel4004_NOP(struct Intel4004_State *state){ /* 0b 0000 0000 */
|
||||
|
||||
++*state->pc;
|
||||
|
||||
INTEL4004_INC_OP;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -141,16 +170,16 @@ void Intel4004_NOP(struct Intel4004_State *state){ /* 0b 0000 0000 */
|
||||
* If *state->pc & 0x08, a one test flag satisfies the condition. */
|
||||
void Intel4004_JCN(struct Intel4004_State *state){ /* 0b 0001 CCCC */
|
||||
|
||||
*state->pc =
|
||||
!INTEL4004_JCN_COND_ISINVERT(state->rom[*state->pc])
|
||||
&& ( (INTEL4004_JCN_COND_ISACCZERO(state->rom[*state->pc])
|
||||
*state->cc =
|
||||
!INTEL4004_JCN_COND_ISINVERT(INTEL4004_THIS_OP)
|
||||
&& ( (INTEL4004_JCN_COND_ISACCZERO(INTEL4004_THIS_OP)
|
||||
&& state->acc == 0)
|
||||
|| (INTEL4004_JCN_COND_ISCARRYON(state->rom[*state->pc])
|
||||
|| (INTEL4004_JCN_COND_ISCARRYON(INTEL4004_THIS_OP)
|
||||
&& state->carry == 1)
|
||||
|| (INTEL4004_JCN_COND_ISTESTON(state->rom[*state->pc])
|
||||
|| (INTEL4004_JCN_COND_ISTESTON(INTEL4004_THIS_OP)
|
||||
&& state->test == 1))
|
||||
? state->rom[*state->pc + 1]
|
||||
: *state->pc + 2;
|
||||
? state->rom[*state->cc + 1]
|
||||
: *state->cc + 2;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -166,14 +195,13 @@ void Intel4004_JCN(struct Intel4004_State *state){ /* 0b 0001 CCCC */
|
||||
/* Fetches an immediate byte from ROM. */
|
||||
void Intel4004_FIM(struct Intel4004_State *state){ /* 0b 0010 RRR0 */
|
||||
|
||||
state->reg[INTEL4004_REGPAIR(state->rom[*state->pc])]
|
||||
= HIGH_NYBBLE(state->rom[*state->pc + 1]);
|
||||
state->reg[INTEL4004_REGPAIR(INTEL4004_THIS_OP)]
|
||||
= HIGH_NYBBLE(INTEL4004_NEXT_OP);
|
||||
|
||||
state->reg[INTEL4004_REGPAIR(state->rom[*state->pc]) + 1]
|
||||
= LOW_NYBBLE(state->rom[*state->pc + 1]);
|
||||
|
||||
*state->pc += 2;
|
||||
state->reg[INTEL4004_REGPAIR(INTEL4004_THIS_OP) + 1]
|
||||
= LOW_NYBBLE(INTEL4004_NEXT_OP);
|
||||
|
||||
INTEL4004_INC2_OP;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -182,3 +210,37 @@ void Intel4004_SRC(struct Intel4004_State *state){ /* 0b 0010 RRR1 */
|
||||
|
||||
void Intel4004_FIN(struct Intel4004_State *state){ /* 0b 0011 RRR0 */
|
||||
}
|
||||
|
||||
/* Loads the immediate value in the low nybble of the opcode into the
|
||||
* accumulator. */
|
||||
void Intel4004_LDM(struct Intel4004_State *state){ /* 0b 1101 DDDD */
|
||||
|
||||
state->acc = LOW_NYBBLE(INTEL4004_THIS_OP);
|
||||
|
||||
INTEL4004_INC_OP;
|
||||
return;
|
||||
}
|
||||
|
||||
void Intel4004_BBL(struct Intel4004_State *state){ /* 0b 1100 DDDD */
|
||||
/* <http://e4004.szyc.org/> lists 0b 1100 RRRR, most likely as a typo. I found
|
||||
* 0b 1100 DDDD on the Intel 4004 datasheet. */
|
||||
|
||||
return Intel4004_LDM(state);
|
||||
}
|
||||
|
||||
/* Clears the carry bit. */
|
||||
void Intel4004_CLC(struct Intel4004_State *state){ /* 0b 1111 0001 */
|
||||
|
||||
state->carry = 0;
|
||||
|
||||
INTEL4004_INC_OP;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clears both the accumulator and the carry bit. */
|
||||
void Intel4004_CLB(struct Intel4004_State *state){ /* 0b 1111 0000 */
|
||||
|
||||
state->acc = 0;
|
||||
|
||||
return Intel4004_CLC(state);
|
||||
}
|
||||
|
73
Wip/bitch/gtk4.c
Normal file
73
Wip/bitch/gtk4.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define BUF 100
|
||||
|
||||
static GtkApplication *app;
|
||||
|
||||
static void activate(GtkApplication *app, gpointer user_data);
|
||||
static void button_pressed(GtkWidget *button, gpointer data);
|
||||
|
||||
static void
|
||||
activate(GtkApplication *app, gpointer user_data){
|
||||
GtkWidget *box;
|
||||
GtkWidget *button;
|
||||
int c;
|
||||
char *s;
|
||||
GtkWidget *scrolledwindow;
|
||||
GtkWidget *window;
|
||||
|
||||
window = gtk_application_window_new(app);
|
||||
gtk_window_set_title(GTK_WINDOW(window), "Bitch");
|
||||
gtk_window_set_default_size(GTK_WINDOW(window), h, v);
|
||||
|
||||
scrolledwindow = gtk_scrolled_window_new();
|
||||
gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(scrolledwindow), 1);
|
||||
gtk_window_set_child(GTK_WINDOW(window), scrolledwindow);
|
||||
|
||||
box = gtk_list_box_new();
|
||||
//gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
|
||||
//gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrolledwindow), box);
|
||||
|
||||
for(;;){
|
||||
if(sip() == NULL)
|
||||
break;
|
||||
button = gtk_button_new_with_label(buf);
|
||||
g_signal_connect(
|
||||
button, "clicked", G_CALLBACK(button_pressed), NULL
|
||||
);
|
||||
gtk_list_box_insert(GTK_LIST_BOX(box), button, -1);
|
||||
}
|
||||
|
||||
gtk_window_present(GTK_WINDOW(window));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed(GtkWidget *button, gpointer data){
|
||||
|
||||
switch(f){
|
||||
case 'w':
|
||||
g_print("%s\n", gtk_button_get_label(GTK_BUTTON(button)));
|
||||
break;
|
||||
case 'x':
|
||||
system(gtk_button_get_label(GTK_BUTTON(button)));
|
||||
break;
|
||||
}
|
||||
if(shy)
|
||||
g_application_quit(G_APPLICATION(app));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int setup(){
|
||||
app = gtk_application_new(
|
||||
"org.trinity.femaledog", G_APPLICATION_FLAGS_NONE
|
||||
);
|
||||
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
|
||||
status = g_application_run(G_APPLICATION(app), 1, fake_argv);
|
||||
g_object_unref(app);
|
||||
|
||||
return status;
|
||||
}
|
42
Wip/bitch/motif.c
Normal file
42
Wip/bitch/motif.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <Xm/Xm.h>
|
||||
#include <Xm/PushB.h>
|
||||
|
||||
static XtAppContext app_context;
|
||||
|
||||
static void activate(void);
|
||||
static void button_pressed(
|
||||
Widget w, XtPointer client_data, XmPushButtonCallbackStruct *cbs
|
||||
);
|
||||
|
||||
void setup(void){
|
||||
Widget button;
|
||||
Widget top_wid;
|
||||
|
||||
top_wid = XtVaAppInitialize(
|
||||
&app_context, "Bitch", NULL, 0, &fake_argc, fake_argv, NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
for(;;){
|
||||
if(sip() == NULL)
|
||||
break;
|
||||
|
||||
button = XmCreatePushButton(top_wid, buf, NULL, 0);
|
||||
XtManageChild(button);
|
||||
XtAddCallback(button, XmNactivateCallback, button_pressed, NULL);
|
||||
}
|
||||
|
||||
XtRealizeWidget(top_wid);
|
||||
XtAppMainLoop(app_context);
|
||||
}
|
||||
|
||||
static void
|
||||
button_pressed(
|
||||
Widget w,
|
||||
XtPointer client_data,
|
||||
XmPushButtonCallbackStruct *cbs
|
||||
){
|
||||
printf("pressed\n");
|
||||
if(shy)
|
||||
XtAppSetExitFlag(app_context);
|
||||
}
|
65
Wip/bitswap/bitswap.c
Normal file
65
Wip/bitswap/bitswap.c
Normal file
@ -0,0 +1,65 @@
|
||||
#include <stdio.h> /* fgetc(3), fprintf(3), fputc(3), stderr, stdin, stdout,
|
||||
* EOF */
|
||||
#include <sysexits.h> /* EX_OK, EX_USAGE */
|
||||
#include <unistd.h> /* getopt(3) */
|
||||
|
||||
/* untested */
|
||||
|
||||
int
|
||||
usage(char *argv0) {
|
||||
(void)fprintf(stderr, "Usage: %s\n", argv0);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int c;
|
||||
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "")) != -1) {
|
||||
switch (c) {
|
||||
default: return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// Swapping algorithm: For example, say c is 0b0101_0101 */
|
||||
// /* <<< <<<< */
|
||||
// c <<= 7; /* Now 0b010_1010_1000_0000 */
|
||||
// /* ^ >^ */
|
||||
// c |= (c & (1 << 8)) >> 2; /* Now 0b010_1010_1000_0000 */
|
||||
// /* ^> >>^ */
|
||||
// c |= (c & (1 << 9)) >> 4; /* Now 0b010_1010_1010_0000 */
|
||||
// /* ^>> >>>^ */
|
||||
// c |= (c & (1 << 10)) >> 6; /* Now 0b010_1010_1010_0000 */
|
||||
// /* ^>>> >>>> ^ */
|
||||
// c |= (c & (1 << 11)) >> 8; /* Now 0b010_1010_1010_1000 */
|
||||
// /* ^ >>>> >>>> >^ */
|
||||
// c |= (c & (1 << 12)) >> 10; /* Now 0b010_1010_1010_1000 */
|
||||
// /* ^> >>>> >>>> >>^ */
|
||||
// c |= (c & (1 << 13)) >> 12; /* Now 0b010_1010_1010_1010 */
|
||||
// /* ^>> >>>> >>>> >>>^ */
|
||||
// c |= (c & (1 << 14)) >> 14; /* Now 0b010_1010_1010_1010 */
|
||||
// /* & 0b000_0000_1111_1111 */
|
||||
// c &= 0xFF; /* Now 0b1010_1010 */
|
||||
#endif
|
||||
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
|
||||
while ((c = fgetc(stdin)) != EOF) {
|
||||
for (c <<= 7, i = 8; i <= 14; ++i)
|
||||
{ c |= (c & (1 << i)) >> ((i - 7) * 2); }
|
||||
|
||||
if (fputc(c, stdout) == EOF)
|
||||
{ perror(argv[0]); return EX_IOERR; }
|
||||
}
|
||||
if (ferror(stdin) != 0) { perror(argv[0]); return EX_IOERR; }
|
||||
}
|
||||
|
||||
return EX_OK;
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
int
|
||||
isblank(int c){
|
||||
return c == '\t'
|
||||
|| c == ' ';
|
||||
}
|
||||
|
||||
int
|
||||
isspace(int c){
|
||||
return isblank(c)
|
||||
|| c == '\n'
|
||||
|| c == '\v'
|
||||
|| c == '\f'
|
||||
|| c == '\r';
|
||||
}
|
||||
|
||||
int
|
||||
isgraph(int c){ return c >= '!' && c <= '~'; }
|
||||
|
||||
int
|
||||
isprint(int c){ return c == ' ' || isgraph(c); }
|
||||
|
||||
int
|
||||
iscntrl(int c){ return !isprint(c); }
|
||||
|
||||
int
|
||||
isdigit(int c){ return c >= '0' && c <= '9'; }
|
||||
|
||||
int
|
||||
islower(int c){ return c >= 'a' && c <= 'z'; }
|
||||
|
||||
int
|
||||
isupper(int c){ return c >= 'A' && c <= 'Z'; }
|
||||
|
||||
int
|
||||
isxdigit(int c){
|
||||
return
|
||||
isdigit(c)
|
||||
|| (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
int
|
||||
isalpha(int c){ return islower(c) || isupper(c); }
|
||||
|
||||
int
|
||||
isalnum(int c){ return isalpha(c) || isdigit(c) };
|
||||
|
||||
int
|
||||
ispunct(int c){ return c != ' ' && !isalnum(c) };
|
||||
|
||||
int
|
||||
tolower(int c){ return c - isupper(c) * ('A' - 'a'); }
|
||||
|
||||
int
|
||||
toupper(int c){ return c + islower(c) * ('A' - 'a'); }
|
@ -1,17 +0,0 @@
|
||||
#ifndef _CTYPE_H
|
||||
# define CTYPE_H
|
||||
int isblank(int c);
|
||||
int isspace(int c);
|
||||
int isgraph(int c);
|
||||
int isprint(int c);
|
||||
int iscntrl(int c);
|
||||
int isdigit(int c);
|
||||
int islower(int c);
|
||||
int isupper(int c);
|
||||
int isxdigit(int c);
|
||||
int isalpha(int c);
|
||||
int isalnum(int c);
|
||||
int ispunct(int c);
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
#endif /* ifndef _CTYPE_H */
|
@ -1,53 +0,0 @@
|
||||
char *
|
||||
strchr(const char *s, int c){
|
||||
char *r;
|
||||
|
||||
for(r = s; ; ++r){
|
||||
if(*r == c)
|
||||
return r;
|
||||
if(*r == '\0')
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
strrchr(const char *s, int c){
|
||||
char *r;
|
||||
char *p;
|
||||
|
||||
for(p = s, r = NULL; ; ++p){
|
||||
if(*p == c)
|
||||
r = p;
|
||||
if(*p == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
strchrnul(const char *s, int c){
|
||||
char *r;
|
||||
|
||||
for(r = s; ; ++r)
|
||||
if(*r == c || r == '\0')
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
strlen(const char *s){
|
||||
size_t r;
|
||||
|
||||
for(r = 0; s[r] != '\0'; ++r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t
|
||||
strnlen(const char *s, size_t maxlen){
|
||||
size_t r;
|
||||
|
||||
for(r = 0; s[r] != '\0' && r < maxlen; ++r);
|
||||
|
||||
return r;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef _STRING_H
|
||||
# define _STRING_H
|
||||
char * strchr(const char *s, int c);
|
||||
char * strrchr(const char *s, int c);
|
||||
char *strchrnul(const char *s, int c);
|
||||
size_t strlen(const char *s);
|
||||
size_t strnlen(const char *s, size_t maxlen);
|
||||
#endif /* ifndef _STRING_H */
|
@ -1,12 +1,26 @@
|
||||
#include <stdio.h>
|
||||
#include <stdio.h> /* fprintf(3), stderr */
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> /* getopt(3) */
|
||||
|
||||
/* The philosophical bits - /should this be a shell script?/ -
|
||||
* are more complicated than the actual program. sed(1) is not currently a part
|
||||
* of this project so there shouldn't be reliance on it. */
|
||||
static int lines = 10; /* POSIX.1 */
|
||||
static char *program_name = "head";
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
char *argv0 = argv[0];
|
||||
size_t i;
|
||||
int c;
|
||||
extern char *optarg;
|
||||
extern int opterr, optind, optopt;
|
||||
|
||||
|
||||
if(argc > 0)
|
||||
program_name = argv[0];
|
||||
|
||||
while((c = getopt(argc, argv, "n:")) != -1)
|
||||
switch(c){
|
||||
case 'n':
|
||||
break;
|
||||
default:
|
||||
#ifdef IGIT /* parse -[digit] options */
|
||||
#endif /* ifdef IGIT */
|
||||
usage: fprintf(stderr, "Usage: %s (-n [lines]) (file...)\n",
|
||||
program_name);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
@ -9,3 +9,5 @@ def main(buffer, command):
|
||||
except Exception as err:
|
||||
print("%s" % str(err))
|
||||
return buffer
|
||||
|
||||
bang = main
|
||||
|
@ -3,10 +3,7 @@ import sys
|
||||
from buffer import Buffer
|
||||
from get_command import get_command
|
||||
|
||||
def version():
|
||||
print("it.py line editor; ALPHA 2021")
|
||||
return None
|
||||
|
||||
#$
|
||||
def main(buffer, supplied_command):
|
||||
if supplied_command != [] and len(supplied_command) > 1:
|
||||
command = supplied_command[1:]
|
||||
@ -21,7 +18,8 @@ def main(buffer, supplied_command):
|
||||
if command == []:
|
||||
continue
|
||||
|
||||
if command[0] in buffer.modules.keys() or buffer.import_module_(command[0]):
|
||||
if (command[0] in buffer.modules.keys()
|
||||
or buffer.import_module_(command[0])):
|
||||
buffer = buffer.modules[command[0]].main(buffer, command)
|
||||
if type(buffer) is int:
|
||||
break
|
||||
|
@ -3,57 +3,59 @@
|
||||
char **
|
||||
getpaths(void)
|
||||
{
|
||||
char *p;
|
||||
char **q;
|
||||
char *path;
|
||||
size_t path_s;
|
||||
char *path_temp;
|
||||
char **paths;
|
||||
size_t paths_s;
|
||||
|
||||
if((path_temp = getenv(PATH_NAME)) == NULL){
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
{
|
||||
char *path_temp;
|
||||
size_t path_s;
|
||||
|
||||
if((path_temp = getenv(PATH_NAME)) == NULL)
|
||||
goto bail;
|
||||
|
||||
/* How long is path? */
|
||||
for(path_s = 0; path_temp[path_s] != '\0'; ++path_s);
|
||||
/* path_s has the size of the path string, not including the null
|
||||
* terminator */
|
||||
|
||||
/* getenv's return value mustn't be modified so copy it into memory we
|
||||
* control */
|
||||
if((path = malloc((sizeof *path) * (path_s + 1))) == NULL)
|
||||
goto bail;
|
||||
|
||||
memcpy(path, path_temp, path_s + 1);
|
||||
}
|
||||
|
||||
/* How long is path? */
|
||||
for(path_s = 0; path_temp[path_s] != '\0'; ++path_s);
|
||||
/* path_s has the size of the path string, not including the null
|
||||
* terminator */
|
||||
{
|
||||
char *p;
|
||||
char **q;
|
||||
size_t paths_s;
|
||||
|
||||
/* getenv's return value mustn't be modified so copy it into memory we
|
||||
* control */
|
||||
if((path = malloc(sizeof(char) * (path_s + 1))) == NULL){
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
memcpy(path, path_temp, path_s + 1);
|
||||
path_temp = NULL;
|
||||
path_s = 0; /* This shouldn't be necessary anymore */
|
||||
/* How many paths in $PATH? */
|
||||
for(paths_s = 1, p = path; *p != '\0'; paths_s += *p++ == PATH_DELIMITER);
|
||||
|
||||
/* How many paths in $PATH? */
|
||||
for(paths_s = 1, p = path; *p != '\0'; paths_s += *p++ == PATH_DELIMITER);
|
||||
if((paths = malloc((sizeof *paths) * (paths_s + 1))) == NULL)
|
||||
goto bail1;
|
||||
|
||||
if((paths = malloc(sizeof(char *) * (paths_s + 1))) == NULL){
|
||||
free(path);
|
||||
errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Replace all instances of the path delimiter with 0, and then put the
|
||||
* next path beginning into paths. */
|
||||
/* This way we can get multiple strings out of one span of memory. */
|
||||
for(*paths = p = path, q = paths + 1; *p != '\0';)
|
||||
if(*p++ == PATH_DELIMITER){
|
||||
*(p - 1) = '\0';
|
||||
*q++ = p;
|
||||
}
|
||||
/* Replace all instances of the path delimiter with 0, and then put the
|
||||
* next path beginning into paths. */
|
||||
/* This way we can get multiple strings out of one span of memory. */
|
||||
for(*paths = p = path, q = paths + 1; *p != '\0';)
|
||||
if(*p++ == PATH_DELIMITER){
|
||||
*(p - 1) = '\0';
|
||||
*q++ = p;
|
||||
}
|
||||
|
||||
paths[path_s] = NULL;
|
||||
paths[path_s] = NULL;
|
||||
}
|
||||
|
||||
/* Because paths[0] will always be path, we can just free(*paths) at
|
||||
* the end and discard path */
|
||||
path = NULL;
|
||||
|
||||
return paths;
|
||||
|
||||
bail1: free(path);
|
||||
bail: errno = ENOMEM; /* Cannot allocate memory */
|
||||
return NULL;
|
||||
}
|
||||
|
102
Wip/lsd/Makefile
Normal file
102
Wip/lsd/Makefile
Normal file
@ -0,0 +1,102 @@
|
||||
include hyperlinks.mk
|
||||
|
||||
all: fhs learn
|
||||
|
||||
fhs:
|
||||
# Filesystem Hierarchy Standard 3.0, 2015
|
||||
# https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf
|
||||
|
||||
# section 3.2
|
||||
mkdir -p "$(PREFIX)/bin"
|
||||
mkdir -p "$(PREFIX)/boot"
|
||||
mkdir -p "$(PREFIX)/dev"
|
||||
mkdir -p "$(PREFIX)/etc"
|
||||
mkdir -p "$(PREFIX)/lib"
|
||||
mkdir -p "$(PREFIX)/media"
|
||||
mkdir -p "$(PREFIX)/mnt"
|
||||
mkdir -p "$(PREFIX)/opt"
|
||||
mkdir -p "$(PREFIX)/run"
|
||||
mkdir -p "$(PREFIX)/sbin"
|
||||
mkdir -p "$(PREFIX)/srv"
|
||||
mkdir -p "$(PREFIX)/tmp"
|
||||
mkdir -p "$(PREFIX)/usr"
|
||||
mkdir -p "$(PREFIX)/var"
|
||||
|
||||
# section 3.7.4
|
||||
mkdir -p "$(PREFIX)/etc/opt"
|
||||
|
||||
# section 4.2
|
||||
mkdir -p "$(PREFIX)/usr/bin"
|
||||
mkdir -p "$(PREFIX)/usr/lib"
|
||||
mkdir -p "$(PREFIX)/usr/local"
|
||||
mkdir -p "$(PREFIX)/usr/sbin"
|
||||
mkdir -p "$(PREFIX)/usr/share"
|
||||
|
||||
# section 4.3
|
||||
mkdir -p "$(PREFIX)/usr/include"
|
||||
mkdir -p "$(PREFIX)/var/spool"
|
||||
mkdir -p "$(PREFIX)/var/tmp"
|
||||
mkdir -p "$(PREFIX)/var/lock"
|
||||
ln -s "$(PREFIX)/usr/spool" "$(PREFIX)/var/spool"
|
||||
ln -s "$(PREFIX)/usr/tmp" "$(PREFIX)/var/tmp"
|
||||
ln -s "$(PREFIX)/usr/spool/locks" "$(PREFIX)/var/lock"
|
||||
|
||||
# section 4.6
|
||||
mkdir -p "$(PREFIX)/usr/lib"
|
||||
|
||||
# section 4.9
|
||||
mkdir -p "$(PREFIX)/usr/local"
|
||||
|
||||
# section 4.9.2
|
||||
mkdir -p "$(PREFIX)/usr/local/bin"
|
||||
#mkdir -p "$(PREFIX)/usr/local/etc" # see section 4.9.3
|
||||
mkdir -p "$(PREFIX)/usr/local/games"
|
||||
mkdir -p "$(PREFIX)/usr/local/include"
|
||||
mkdir -p "$(PREFIX)/usr/local/lib"
|
||||
mkdir -p "$(PREFIX)/usr/local/man"
|
||||
mkdir -p "$(PREFIX)/usr/local/sbin"
|
||||
mkdir -p "$(PREFIX)/usr/local/share"
|
||||
mkdir -p "$(PREFIX)/usr/local/src"
|
||||
|
||||
# section 4.9.3
|
||||
ln -s "$(PREFIX)/usr/local/etc" "$(PREFIX)/etc/local"
|
||||
|
||||
# section 4.11.6
|
||||
mkdir -p "$(PREFIX)/usr/share/man"
|
||||
|
||||
# section 4.11.7
|
||||
mkdir -p "$(PREFIX)/usr/share/misc"
|
||||
|
||||
# section 4.12
|
||||
mkdir -p "$(PREFIX)/usr/src"
|
||||
|
||||
# section 5.2
|
||||
mkdir -p "$(PREFIX)/var/lib"
|
||||
mkdir -p "$(PREFIX)/var/local"
|
||||
mkdir -p "$(PREFIX)/var/log"
|
||||
mkdir -p "$(PREFIX)/var/opt"
|
||||
#mkdir -p "$(PREFIX)/var/run" # see section 5.13.2
|
||||
|
||||
# section 5.8.2
|
||||
mkdir -p "$(PREFIX)/var/lib/misc"
|
||||
|
||||
# section 5.13.2
|
||||
ln -s "$(PREFIX)/var/run" "$(PREFIX)/run"
|
||||
|
||||
# section 6.1.10
|
||||
mkdir -p "$(PREFIX)/var/spool/cron"
|
||||
|
||||
$(PREFIX)/usr/src/linux: fhs
|
||||
git clone "$(LINUX_UPSTREAM_GIT)" "$(PREFIX)/usr/src/linux.tmp"
|
||||
mv "$(PREFIX)/usr/src/linux.tmp" "$(PREFIX)/usr/src/linux"
|
||||
|
||||
$(PREFIX)/usr/src/musl: fhs
|
||||
git clone "$(MUSL_UPSTREAM_GIT)" "$(PREFIX)/usr/src/musl.tmp"
|
||||
mv "$(PREFIX)/usr/src/musl.tmp" "$(PREFIX)/usr/src/musl"
|
||||
|
||||
musl: $(PREFIX)/usr/src/musl
|
||||
cd "$(PREFIX)/usr/src/musl"
|
||||
./configure --prefix="$(PREFIX)"
|
||||
$(MAKE) install
|
||||
|
||||
.PHONY: all
|
4
Wip/lsd/hyperlinks.mk
Normal file
4
Wip/lsd/hyperlinks.mk
Normal file
@ -0,0 +1,4 @@
|
||||
GCC_UPSTREAM_GIT=git://gcc.gnu.org/git/gcc.git
|
||||
LINUX_UPSTREAM_GIT=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
MUSL_UPSTREAM_GIT=git://git.musl-libc.org/musl
|
||||
PKGSRC_UPSTREAM_HTTPS=https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc.tar.xz
|
65
Wip/lsd/trilsd.7
Normal file
65
Wip/lsd/trilsd.7
Normal file
@ -0,0 +1,65 @@
|
||||
.TH TRINITX 7
|
||||
|
||||
.SH PRONUNCIATION
|
||||
"Try LSD"
|
||||
|
||||
.SH SYNOPSIS
|
||||
.I TriLSD
|
||||
is a UNIX-like software distribution built upon the Linux kernel and the
|
||||
musl C standard library, with nearly all configuration options left to the
|
||||
user's own device.
|
||||
|
||||
.SH BASE SYSTEM
|
||||
A
|
||||
.I TriLSD
|
||||
system always has the following packages:
|
||||
dash,
|
||||
the GNU compiler collection,
|
||||
GNU make,
|
||||
musl,
|
||||
and
|
||||
linux and util-linux.
|
||||
.PP
|
||||
In addition,
|
||||
.I TriLSD
|
||||
needs a core utilities package.
|
||||
The GNU coreutils are a popular choice but Busybox or your own may be used.
|
||||
.PP
|
||||
.I TriLSD
|
||||
also needs an initialization system.
|
||||
OpenRC is the suggested choice but others may be used.
|
||||
SystemD is discouraged; it's mentioned for its popularity and frowned upon for
|
||||
its generally lax security.
|
||||
|
||||
.SH INSTALLATION
|
||||
To install
|
||||
.I TriLSD
|
||||
most of the POSIX specified utilities including awk, git(1), GNU make, and a C
|
||||
compiler that can build the GNU compiler collection must be installed.
|
||||
|
||||
.PP
|
||||
For the installation process see
|
||||
.RB try (1)
|
||||
|
||||
.SH PACKAGE MANAGEMENT
|
||||
.I TriLSD
|
||||
does not come with a package manager; the user may choose whatever
|
||||
system-independent package manager they prefer.
|
||||
|
||||
.SH CONTRIBUTING
|
||||
Pay attention to projects' guidelines for distributions.
|
||||
.PP
|
||||
musl guidelines: https://wiki.musl-libc.org/guidelines-for-distributions.html
|
||||
|
||||
.SH HISTORY
|
||||
The
|
||||
.I TriLSD
|
||||
project was started 2021-12-28 as Trinitx.
|
||||
|
||||
.SH COPYRIGHT
|
||||
.I TriLSD
|
||||
documentation and all in-house tools are part of the public domain.
|
||||
Components of the distribution are of course subject to their own licenses.
|
||||
|
||||
.SH SEE ALSO
|
||||
.RB try (1)
|
8
Wip/rss/Cargo.toml
Normal file
8
Wip/rss/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "rss"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
@ -1,37 +0,0 @@
|
||||
# pig\_birth
|
||||
|
||||
Initializes the pig.
|
||||
|
||||
# pig\_feed
|
||||
|
||||
Refreshes all the feed in the pigpen.
|
||||
|
||||
# pig\_fetch
|
||||
|
||||
Fetches the feed for the pigpen.
|
||||
|
||||
Not intended to be called on its own.
|
||||
|
||||
# pig\_latin
|
||||
|
||||
Prints internal pig details for a given feed file.
|
||||
|
||||
# pig\_name
|
||||
|
||||
Prints the file name for a given pig feed.
|
||||
|
||||
# pig\_pen
|
||||
|
||||
Prints the location of the pigpen, which houses all stowed pig feed.
|
||||
|
||||
A given feed will be stored as `"$(pig_pen)/$(pig_name)`.
|
||||
|
||||
# pig\_recall
|
||||
|
||||
Prints the contents of a given feed URL.
|
||||
|
||||
If the URL isn't already stowed, stows it before printing.
|
||||
|
||||
# pig\_stow
|
||||
|
||||
Stows fetched feed in the pigpen.
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
argv0="$0"
|
||||
|
||||
depend(){
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
printf "%s: %s: Could not find dependency.\n" "$argv0" "$1" \
|
||||
1>&2
|
||||
exit 69 # sysexits(3) EX_UNAVAILABLE
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
depend curl
|
||||
depend jq
|
||||
depend xq
|
||||
|
||||
mkdir "$(pig_pen)"
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
for file in "$(pig_pen)"/*; do
|
||||
pig_latin "$file" \
|
||||
| jq '.feed_url' \
|
||||
| xargs pig_stow &
|
||||
done
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
curl -so - -- "$1"
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
while str isvalue "$1"; do
|
||||
case "$1" in
|
||||
*xml)
|
||||
xq '.feed.pig' <"$1" ;;
|
||||
*json)
|
||||
jq '.feed.pig' <"$1" ;;
|
||||
esac
|
||||
done
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf "%s\n" "$1" \
|
||||
| tr -cd '[:alnum:]'
|
@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
str isvalue "$1" \
|
||||
&& printf "Usage: %s\n" "$0" 1>&2 \
|
||||
&& exit 64 \
|
||||
|| str isvalue "$PIGPEN" \
|
||||
&& printf "%s\n" "$PIGPEN" \
|
||||
&& exit 0 \
|
||||
|| str isvalue "$XDG_CONFIG_HOME" \
|
||||
&& printf "%s\n" "$XDG_CONFIG_HOME" \
|
||||
&& exit 0 \
|
||||
|| printf "%s/.pigpen\n" "$HOME" \
|
||||
&& exit 0 \
|
||||
|| exit 1
|
@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
filename="$(pig_pen)/$(pig_name "$1")"
|
||||
|
||||
test -e "$filename" || pig_stow "$1"
|
||||
cat "$filename"
|
@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
while str isvalue "$1"; do
|
||||
|
||||
pig_fetch "$1" | xq -x "$(
|
||||
printf '.
|
||||
* { feed: { pig: {
|
||||
feed_url: "%b",
|
||||
pet_sound: "oink",
|
||||
stow_date: "%b",
|
||||
version: "0"
|
||||
} } }' "$1" "$(date '+%Y-%m-%dT%T')"\
|
||||
| tr -d '[:space:]' \
|
||||
)" >"$(pig_pen)/$(pig_name "$1")"
|
||||
|
||||
shift
|
||||
done
|
9
Wip/rss/src/main.rs
Normal file
9
Wip/rss/src/main.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use json;
|
||||
fn feed() {
|
||||
|
||||
}
|
||||
fn stow(title: String) {
|
||||
|
||||
}
|
||||
fn main() {
|
||||
}
|
182
Wip/rss/youtube
182
Wip/rss/youtube
@ -1,182 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
argv0="$0"
|
||||
|
||||
PIGPEN="$(pig_pen)"
|
||||
|
||||
latin(){
|
||||
case "$1" in
|
||||
*json) jq '.feed.pig' <"$1" ;;
|
||||
*xml) xq '.feed.pig' <"$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
list_channels(){
|
||||
pscat \
|
||||
[ sh -c "for file in \"$PIGPEN\"/*.xml; \
|
||||
do xq '{(.feed.link[0].\"@href\"): .feed.title}' \"\$file\"; \
|
||||
done 2>/dev/null" ] \
|
||||
[ sh -c "for file in \"$PIGPEN\"/*.json; \
|
||||
do jq '{(.feed.link[0].\"@href\"): .feed.title}' \"\$file\"; \
|
||||
done 2>/dev/null" ] \
|
||||
[ printf "\n" ] \
|
||||
| sed \
|
||||
-e '/{/d' \
|
||||
-e '/}/d' \
|
||||
-e 's/^ \"//g' \
|
||||
-e 's/\": \"/ /g' \
|
||||
-e 's/\,$//g' \
|
||||
-e 's/\"$//g'
|
||||
}
|
||||
|
||||
list_videos(){
|
||||
file="$(printf "$PIGPEN"/$( \
|
||||
list_channels \
|
||||
| sed "/$1/q" \
|
||||
| tail -n 1 \
|
||||
| cut -f 1 \
|
||||
| xargs pig_name \
|
||||
)*)"
|
||||
case "$file" in
|
||||
*json)
|
||||
jq \
|
||||
'reduce .feed.entry[] as $item (
|
||||
{};
|
||||
. + { ($item.link."@href"): $item.title }
|
||||
)' "$file"
|
||||
;;
|
||||
*xml)
|
||||
xq \
|
||||
'reduce .feed.entry[] as $item (
|
||||
{};
|
||||
. + { ($item.link."@href"): $item.title }
|
||||
)' "$file"
|
||||
;;
|
||||
*)
|
||||
printf "No file found!\n" 1>&2
|
||||
true
|
||||
;;
|
||||
esac | sed \
|
||||
-e '1d' \
|
||||
-e '$d' \
|
||||
-e 's/\": \"/ /g' \
|
||||
-e 's/^ \"//g' \
|
||||
-e 's/\,$//g' \
|
||||
-e 's/\"$//g' # this is really hacky
|
||||
|
||||
}
|
||||
|
||||
stow(){
|
||||
name="$PIGPEN/$(pig_name "$1")"
|
||||
pig_fetch "$1" | xq "$(
|
||||
date '+%Y-%m-%dT%T' \
|
||||
| xargs printf '
|
||||
. * { feed: { pig: {
|
||||
feed_url: "%b",
|
||||
pet_sound: "choo",
|
||||
stow_date: "%b",
|
||||
version: "0"
|
||||
} } }' "$1" \
|
||||
)" >"$name.json"
|
||||
rm -f "$name.xml"
|
||||
}
|
||||
|
||||
watch(){
|
||||
youtube-dl -F "$1"
|
||||
printf "Pick a format [22]: "
|
||||
input="$(head -n 1 | tr -d '\n')"
|
||||
str isalnum "$input" \
|
||||
&& str isdigit $input \
|
||||
|| input=22 \
|
||||
&& youtube-dl -f $input "$1" -o - \
|
||||
| mpv -
|
||||
}
|
||||
|
||||
usage(){
|
||||
printf "\
|
||||
Usage: %s
|
||||
list_channels
|
||||
list_videos [channel name]
|
||||
listen [video URL]
|
||||
refresh (channel name...)
|
||||
subscribe [channel URL...]
|
||||
watch [video URL]
|
||||
watch_latest [channel name]
|
||||
" "$argv0" 1>&2
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
list_channels)
|
||||
! str isvalue "$2" \
|
||||
|| usage
|
||||
list_channels
|
||||
;;
|
||||
list_videos) # do something with youtube-dl?
|
||||
list_videos "$2"
|
||||
;;
|
||||
listen)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do youtube-dl "$2" -f bestaudio -o - \
|
||||
| mpv -
|
||||
shift
|
||||
done
|
||||
;;
|
||||
refresh)
|
||||
if ! str isvalue "$2"
|
||||
then for file in "$PIGPEN"/*
|
||||
do stow "$( \
|
||||
latin "$file" \
|
||||
| jq -r '.feed_url' \
|
||||
)"
|
||||
done
|
||||
else
|
||||
while str isvalue "$2"
|
||||
do stow "$( \
|
||||
latin "$( \
|
||||
list_channels \
|
||||
| grep "$2" \
|
||||
| cut -f 2 \
|
||||
)" | jq '.feed_url' \
|
||||
)"
|
||||
shift
|
||||
done
|
||||
fi
|
||||
;;
|
||||
subscribe)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do stow "http://www.youtube.com/feeds/videos.xml?channel_id=$(
|
||||
youtube-dl \
|
||||
--get-filename \
|
||||
--playlist-items 1 \
|
||||
-o '%(channel_id)s' \
|
||||
"$2" \
|
||||
)"
|
||||
shift
|
||||
done
|
||||
;;
|
||||
watch) # needs work
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
while str isvalue "$2"
|
||||
do watch "$2"
|
||||
done
|
||||
;;
|
||||
watch_latest)
|
||||
str isvalue "$2" \
|
||||
|| usage
|
||||
watch "$( \
|
||||
list_videos "$2" \
|
||||
| head -n 1 \
|
||||
| cut -f 1 \
|
||||
)"
|
||||
;;
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
exit 0
|
@ -1,13 +1,8 @@
|
||||
TARGETS = sysexits sysexits.h
|
||||
CFLAGS = -I..
|
||||
all: sysexits sysexits.h
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
clean:
|
||||
rm -f $(TARGETS)
|
||||
|
||||
%: %.c
|
||||
$(CC) $(CFLAGS) -o $@ $@.c
|
||||
sysexits: sysexits.c
|
||||
|
||||
sysexits.h: sysexits
|
||||
./sysexits >sysexits.h
|
||||
|
||||
.PHONY: all
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "arraylen.h"
|
||||
|
||||
/* Thanks to u/smcameron on Reddit. */
|
||||
|
||||
@ -12,7 +11,7 @@
|
||||
* technicality.
|
||||
* I implemented sysexits(3) in the enum method before reading the BSD 4.0
|
||||
* source to see how they did it. */
|
||||
#define ENUM 1
|
||||
#define DEFINE 1
|
||||
|
||||
static char *program_name = "sysexits";
|
||||
|
||||
|
21
Wip/sysexits/sysexits.h
Normal file
21
Wip/sysexits/sysexits.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _SYSEXITS_H
|
||||
# define _SYSEXITS_H
|
||||
enum{
|
||||
EX_OK = 0,
|
||||
EX_USAGE = 64,
|
||||
EX_DATAERR = 65,
|
||||
EX_NOINPUT = 66,
|
||||
EX_NOUSER = 67,
|
||||
EX_NOHOST = 68,
|
||||
EX_UNAVAILABLE = 69,
|
||||
EX_SOFTWARE = 70,
|
||||
EX_OSERR = 71,
|
||||
EX_OSFILE = 72,
|
||||
EX_CANTCREAT = 73,
|
||||
EX_IOERR = 74,
|
||||
EX_TEMPFAIL = 75,
|
||||
EX_PROTOCOL = 76,
|
||||
EX_NOPERM = 77,
|
||||
EX_CONFIG = 78
|
||||
};
|
||||
#endif /* ifndef _SYSEXITS_H */
|
@ -1,3 +0,0 @@
|
||||
- move executables somewhere in path
|
||||
- `$ toki_update` to fetch dictionary
|
||||
- `$ toki_sitelen` to tokiponize
|
@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
toki_ucsur "$@" | utf8
|
@ -1,23 +1,22 @@
|
||||
Comic Book Archives (CB7, CBR, CBZ)
|
||||
|
||||
<http://justsolve.archiveteam.org/wiki/Comic_Book_Archive>
|
||||
<https://en.wikipedia.org/wiki/Comic_book_archive>
|
||||
|
||||
A Comic Book Archive is just an archive with a bunch of sequentially-named
|
||||
images in it which collate ASCIIbetically to the order in which they should be
|
||||
read. Each image corresponds to a page presented by a comic book reader and a
|
||||
Comic Book Archive represents a digital comic book.
|
||||
|
||||
No guarantees can be made regarding image format, image names (though you can
|
||||
expect them to match [:digit:]*\..*; that is, a bunch of numbers followed by a
|
||||
file extension), archive attributes (compression or metadata), or what is in
|
||||
archives besides the images. In fact, when a comic book only has one image, the
|
||||
most common type of file in a comic book archive may not be an image at all.
|
||||
No guarantees can be made regarding image format, image names, archive
|
||||
attributes (compression or metadata), or what is in archives besides the
|
||||
images. In fact, when a comic book only has one image, the most common type of
|
||||
file in a comic book archive may not be an image at all.
|
||||
|
||||
The extension corresponds to what type of archive is being used. I haven't seen
|
||||
an extension that hasn't fit within DOS 8.3, which makes sense as amateur
|
||||
skiddies and repackers mostly use Windows.
|
||||
|
||||
<http://justsolve.archiveteam.org/wiki/Comic_Book_Archive>
|
||||
<https://en.wikipedia.org/wiki/Comic_book_archive>
|
||||
|
||||
Here's a table of Comic Book Archive types. I can't imagine this list is
|
||||
comprehensive but I can't find more on-line.
|
||||
____________________
|
||||
@ -32,10 +31,12 @@ comprehensive but I can't find more on-line.
|
||||
|
||||
I normalize the files I get to the following settings:
|
||||
|
||||
ARCHIVE: PKzip. DEFLATE algorithm. No other configuration.
|
||||
ARCHIVE: PKzip. DEFLATE algorithm. No other configuration and no
|
||||
subdirectories. ($ zip -jZ DEFLATE)
|
||||
CONTENTS: ONLY images. Whatever encoding in which I found them.
|
||||
Sequential naming starting from one, with leading zeroes to ensure file
|
||||
names are all the same length.
|
||||
names are all the same length. e.g. 5 pages are 1-5.ext, but 15 are
|
||||
01-15.ext
|
||||
|
||||
<https://en.wikipedia.org/wiki/7-Zip>
|
||||
7-Zip is free and open source. There are a number of implementations and you
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
usage(){
|
||||
printf 'Usage: %s [files...]\n' "$0"
|
||||
@ -22,9 +22,10 @@ else trap 'rm -rf "$d"; trap - EXIT; exit' EXIT INT HUP
|
||||
fi
|
||||
|
||||
while test -n "$1"; do
|
||||
unrar x -op"$d" "$1"
|
||||
zip -jZ deflate "$1".cbz "$d"/*
|
||||
rm "$d"/*
|
||||
# unrar x -op"$d" "$1"
|
||||
bsdtar xf "$1" -C "$d"
|
||||
zip -jrZ deflate "$1".cbz "$d"/*
|
||||
rm -r "$d"/*
|
||||
shift
|
||||
done
|
||||
|
||||
|
100
cbz/cbzcat
100
cbz/cbzcat
@ -10,49 +10,79 @@ usage(){
|
||||
test -n "$2" \
|
||||
|| usage
|
||||
|
||||
d="$(mktemp -d || printf '%s/.cbzcat' "$HOME/")"
|
||||
trap 'rm -rf "$d"; trap - EXIT; exit' EXIT INT HUP
|
||||
mkdir -p "$d"/x
|
||||
d="$(mktemp -d || printf '%s/.cbzcat\n' "$HOME/")"
|
||||
if test -n "$DEBUG"; then
|
||||
printf 'Using temporary directory %s\n' "$d"
|
||||
set -x
|
||||
else
|
||||
trap 'rm -rf "$d"; trap - EXIT; exit' EXIT INT HUP
|
||||
fi
|
||||
|
||||
i=1 # index
|
||||
il=1 # index length in digits
|
||||
parallel \
|
||||
test -e {} \
|
||||
::: "$@" \
|
||||
|| usage
|
||||
|
||||
for f in "$@"; do
|
||||
test -e "$f" \
|
||||
|| usage
|
||||
parallel --bar \
|
||||
unzip -qqd "$d/"{#} {} \
|
||||
::: "$@"
|
||||
|
||||
unzip -d "$d"/x "$f"
|
||||
# num is created by the shell (parallel in this case) before the pipeline is
|
||||
# run, so we have to compensate for it already being in the directory when the
|
||||
# files are listed
|
||||
parallel \
|
||||
rm -f {}/*.xml \; \
|
||||
ls {} \
|
||||
\| grep -v \
|
||||
-e '^num$' \
|
||||
\| wc -l \
|
||||
\>{}/num \; \
|
||||
printf '0\\n' \
|
||||
'>>'{}/prevs \; \
|
||||
::: "$d"/*
|
||||
|
||||
rm -f "$d"/x/*.xml
|
||||
parallel \
|
||||
test {1/} -lt {2/} \
|
||||
'&&' dd \
|
||||
'<'{1}/num \
|
||||
'>>'{2}/prevs \
|
||||
'2>'/dev/null \
|
||||
'||' true \
|
||||
::: "$d"/* \
|
||||
::: "$d"/*
|
||||
|
||||
for g in "$d"/x/*; do
|
||||
# if there aren't enough leading zeroes
|
||||
if ! printf '%s' "$i" \
|
||||
| wc -c \
|
||||
| xargs test "$il" =; then
|
||||
for h in "$d"/*
|
||||
do test "$h" = "$d"/x \
|
||||
|| printf '%s\n' "$h" \
|
||||
| sed 's|[^/]*$|0&|' \
|
||||
| xargs mv "$h"
|
||||
done
|
||||
# update index digit length
|
||||
il="$(printf '1 + %s\n' "$il" | bc)"
|
||||
fi
|
||||
parallel \
|
||||
\<{}/prevs \
|
||||
sed 's/\\$/ + /' \
|
||||
\| tr -d '\n' \
|
||||
\| sed 's/ + \\$//' \
|
||||
\| bc \
|
||||
\>{}/sum \
|
||||
::: "$d"/*
|
||||
|
||||
# move file to indexed position
|
||||
printf '%s\n' "$g" \
|
||||
| sed 's|^.*\.||' \
|
||||
| xargs printf '%s/%s%s\n' "$d" "$i". \
|
||||
| xargs mv "$g"
|
||||
false
|
||||
|
||||
# increment i
|
||||
i="$(printf '1 + %s\n' "$i" | bc)"
|
||||
done
|
||||
done
|
||||
parallel \
|
||||
ls {}/../ \; \
|
||||
parallel -I [] --arg-sep :::: \
|
||||
test [] -lt {} \
|
||||
'&&' '<'[]/num xargs \
|
||||
printf '%s + ' \
|
||||
:::: {}/../* \
|
||||
\| sed 's| + $||' \
|
||||
\| bc \
|
||||
\>{}/prevs \
|
||||
::: "$d"/*
|
||||
|
||||
rm -r "$d"/x
|
||||
|
||||
zip -Z deflate out.cbz "$d"/*
|
||||
|
||||
mkdir "$d"/0
|
||||
|
||||
false
|
||||
|
||||
parallel --dry-run sh -c "\
|
||||
for dir in "
|
||||
|
||||
zip -Z deflate out.cbz "$d"/0/*
|
||||
|
||||
rm -r "$d"
|
||||
|
@ -27,19 +27,12 @@ CFLAGS = \
|
||||
|
||||
LDFLAGS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
|
||||
|
||||
dmenubar: config.h dmenubar.o drw.h drw.o util.o
|
||||
@echo dmenu build options:
|
||||
@echo "CFLAGS = $(CFLAGS)"
|
||||
@echo "LDFLAGS = $(LDFLAGS)"
|
||||
@echo "CC = $(CC)"
|
||||
dmenubar: dmenubar.o drw.h drw.o util.o
|
||||
$(CC) -o $@ dmenubar.o drw.o util.o $(LDFLAGS)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
config.h:
|
||||
cp config.def.h $@
|
||||
|
||||
clean:
|
||||
rm -f dmenubar *.o
|
||||
|
||||
|
@ -1,75 +1,76 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
|
||||
/* This is a hack I did years ago. Fork dmenu and start from there if you can.
|
||||
* ~ trinity */
|
||||
|
||||
#include <locale.h> /* setlocale(3), LC_CTYPE */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* strlen(3) */
|
||||
#include <stdio.h> /* fprintf(3), stderr */
|
||||
#include <sysexits.h> /* EX_USAGE */
|
||||
#include <unistd.h> /* getopt(3) */
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib.h> /* XSupportsLocale(3), Display, Window */
|
||||
#include <X11/Xutil.h>
|
||||
#ifdef XINERAMA
|
||||
# include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
#include <X11/Xft/Xft.h>
|
||||
#include "drw.h"
|
||||
#include "util.h"
|
||||
|
||||
#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \
|
||||
* MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
|
||||
#include <X11/Xft/Xft.h> /* XftColor */
|
||||
#include "drw.h" /* drw_clr_create(3), drw_create(3), drw_fontset_create(3),
|
||||
* drw_fontset_getwidth(3), drw_free(3), drw_map(3),
|
||||
* drw_resize(3), drw_setscheme(3), drw_rect(3), drw_text(3),
|
||||
* Drw */
|
||||
|
||||
/* chars to be allocated for the text displayed in the bar */
|
||||
#define BUFSIZE 1024
|
||||
|
||||
enum { Scheme, SchemeLast }; /* color schemes */
|
||||
/* enumerated because Suckless has SchemeNorm, SchemeSel, etc.
|
||||
* should be made into like one char *Scheme[2] */
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
||||
static int bh;
|
||||
static XClassHint ch = {"dmenubar", "dmenubar"};
|
||||
static Display *dpy;
|
||||
static Drw *drw;
|
||||
static char *embed;
|
||||
static int inputw = 0;
|
||||
static int lrpad; /* sum of left and right padding */
|
||||
static int mh;
|
||||
static int mon = -1;
|
||||
static int mw;
|
||||
static Window parentwin;
|
||||
static Window root;
|
||||
static Clr *scheme[SchemeLast];
|
||||
static int screen;
|
||||
static Window win;
|
||||
|
||||
#define BREAK_ON_EOF 0
|
||||
#define bool char
|
||||
static struct {
|
||||
bool topbar; /* -b */
|
||||
char *bg_hex; /* -B */
|
||||
bool break_on_eof; /* -e */
|
||||
char *fg_hex; /* -F */
|
||||
int mon; /* -m */
|
||||
char *embed; /* -w */
|
||||
} args;
|
||||
#undef bool
|
||||
|
||||
/* -f option overrides fonts[0]; default X11 font or font set */
|
||||
static const char *fonts[] = {
|
||||
"monospace:size=10"
|
||||
};
|
||||
#define topbar_default 1
|
||||
static char *bg_hex_default = "#005577";
|
||||
#define break_on_eof_default 0
|
||||
static char *fg_hex_default = "#EEEEEE";
|
||||
#define mon_default -1
|
||||
#define embed_default NULL
|
||||
|
||||
static const char *colors[SchemeLast][2] = {
|
||||
/* fg, bg */
|
||||
[Scheme] = { "#eeeeee", "#005577" }
|
||||
/* default X11 font or font set */
|
||||
static const char *fonts[] = { /* drw_fontset_create(3) wants const char ** */
|
||||
"monospace:size=10" /* -f overrides this */
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]){
|
||||
int bh;
|
||||
XftColor bg;
|
||||
int c;
|
||||
Display *dpy;
|
||||
Drw *drw;
|
||||
unsigned int du;
|
||||
Window dw;
|
||||
Window *dws;
|
||||
XftColor fg;
|
||||
int i;
|
||||
int j;
|
||||
int lrpad; /* sum of left and right padding */
|
||||
int mh;
|
||||
int mw;
|
||||
extern char *optarg;
|
||||
Window parentwin;
|
||||
Window root;
|
||||
int screen;
|
||||
XSetWindowAttributes swa;
|
||||
char text[BUFSIZE];
|
||||
int topbar; /* 0=bottom 1=top */
|
||||
Window w;
|
||||
XWindowAttributes wa;
|
||||
Window win;
|
||||
int x;
|
||||
int y;
|
||||
#ifdef XINERAMA
|
||||
@ -78,110 +79,147 @@ main(int argc, char *argv[]){
|
||||
int a, di, n, area = 0;
|
||||
#endif
|
||||
|
||||
topbar = 1;
|
||||
args.topbar = topbar_default;
|
||||
args.bg_hex = bg_hex_default;
|
||||
args.break_on_eof = break_on_eof_default;
|
||||
args.fg_hex = fg_hex_default;
|
||||
args.mon = mon_default;
|
||||
args.embed = embed_default;
|
||||
while((c = getopt(argc, argv, ":bf:m:B:F:w:")) != -1)
|
||||
switch(c){
|
||||
case 'b':
|
||||
topbar = 0;
|
||||
args.topbar = !args.topbar;
|
||||
break;
|
||||
case 'e':
|
||||
args.break_on_eof = !args.break_on_eof;
|
||||
break;
|
||||
case 'B': if(optarg){
|
||||
colors[Scheme][ColBg] = optarg;
|
||||
args.bg_hex = optarg;
|
||||
break;
|
||||
}case 'f': if(optarg){
|
||||
fonts[0] = optarg;
|
||||
break;
|
||||
}case 'F': if(optarg){
|
||||
colors[Scheme][ColFg] = optarg;
|
||||
args.fg_hex = optarg;
|
||||
break;
|
||||
}case 'm': if(optarg){
|
||||
mon = atoi(optarg);
|
||||
args.mon = atoi(optarg);
|
||||
break;
|
||||
}case 'w': if(optarg){
|
||||
embed = optarg;
|
||||
args.embed = optarg;
|
||||
break;
|
||||
}default: /* optarg==0 falls through */
|
||||
fprintf(stderr,
|
||||
"Usage: %s (-b) (-B [background color])"
|
||||
"Usage: %s (-be) (-B [background color])"
|
||||
"(-f [font]) (-F foreground color)\n"
|
||||
"\t(-m [monitor]) (-w [windowid)\n",
|
||||
argv[0]);
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
||||
if(setlocale(LC_CTYPE, "") == NULL || !XSupportsLocale())
|
||||
fprintf(stderr, "%s: No locale support.\n", argv[0]);
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("cannot open display");
|
||||
|
||||
if((dpy = XOpenDisplay(NULL)) == NULL){
|
||||
fprintf(stderr, "%s: Cannot open X display.\n", argv[0]);
|
||||
return EX_UNAVAILABLE;
|
||||
}
|
||||
screen = DefaultScreen(dpy);
|
||||
root = RootWindow(dpy, screen);
|
||||
if (!embed || !(parentwin = strtol(embed, NULL, 0)))
|
||||
if (args.embed == NULL || !(parentwin = strtol(args.embed, NULL, 0)))
|
||||
parentwin = root;
|
||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
||||
die("could not get embedding window attributes: 0x%lx",
|
||||
parentwin);
|
||||
if (!XGetWindowAttributes(dpy, parentwin, &wa)){
|
||||
fprintf(stderr, "%s: Could not get embedding window "
|
||||
"attributes: 0x%lx", argv[0], parentwin);
|
||||
return EX_UNAVAILABLE;
|
||||
}
|
||||
drw = drw_create(dpy, screen, root, wa.width, wa.height);
|
||||
if (!drw_fontset_create(drw, fonts, (sizeof fonts) / (sizeof *fonts)))
|
||||
die("no fonts could be loaded.");
|
||||
if (!drw_fontset_create(drw, fonts, (sizeof fonts) / (sizeof *fonts))){
|
||||
fprintf(stderr, "%s: No fonts could be loaded.\n", argv[0]);
|
||||
return EX_UNAVAILABLE;
|
||||
}
|
||||
lrpad = drw->fonts->h;
|
||||
|
||||
/* ??? */
|
||||
#ifdef __OpenBSD__
|
||||
if (pledge("stdio rpath", NULL) == -1)
|
||||
die("pledge");
|
||||
if(pledge("stdio rpath", NULL) == -1){
|
||||
fprintf(stderr, "%s: Could not pledge(2).\n", argv[0]);
|
||||
return EX_UNAVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* init appearance */
|
||||
for (j = 0; j < SchemeLast; j++)
|
||||
scheme[j] = drw_scm_create(drw, colors[j], 2);
|
||||
drw_clr_create(drw, &bg, args.bg_hex);
|
||||
drw_clr_create(drw, &fg, args.fg_hex);
|
||||
|
||||
/* calculate menu geometry */
|
||||
bh = drw->fonts->h + 2;
|
||||
mh = bh;
|
||||
#ifdef XINERAMA
|
||||
# define INTERSECT(x, y, w, h, r) (\
|
||||
MAX(0, \
|
||||
MIN((x) + (w), (r).x_org + (r).width) \
|
||||
- MAX((x), (r).x_org)) \
|
||||
* MAX(0, \
|
||||
MIN((y) + (h), (r).y_org + (r).height) \
|
||||
- MAX((y), (r).y_org))\
|
||||
)
|
||||
i = 0;
|
||||
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
|
||||
if(parentwin == root && (info = XineramaQueryScreens(dpy, &n))){
|
||||
XGetInputFocus(dpy, &w, &di);
|
||||
if (mon >= 0 && mon < n)
|
||||
i = mon;
|
||||
else if (w != root && w != PointerRoot && w != None) {
|
||||
/* find top-level window containing current input focus */
|
||||
do {
|
||||
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
|
||||
if(args.mon >= 0 && args.mon < n)
|
||||
i = args.mon;
|
||||
else if(w != root && w != PointerRoot && w != None){
|
||||
/* find top-level window containing current input focus
|
||||
*/
|
||||
do{
|
||||
if( XQueryTree(dpy, (pw = w), &dw,
|
||||
&w, &dws, &du)
|
||||
&& dws)
|
||||
XFree(dws);
|
||||
} while (w != root && w != pw);
|
||||
/* find xinerama screen with which the window intersects most */
|
||||
if (XGetWindowAttributes(dpy, pw, &wa))
|
||||
for (j = 0; j < n; j++)
|
||||
if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
|
||||
}while(w != root && w != pw);
|
||||
/* find xinerama screen with which the window
|
||||
* intersects most */
|
||||
if(XGetWindowAttributes(dpy, pw, &wa))
|
||||
for(j = 0; j < n; j++)
|
||||
if( (a = INTERSECT(wa.x,
|
||||
wa.y, wa.width,
|
||||
wa.height,
|
||||
info[j]))
|
||||
> area){
|
||||
area = a;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
/* no focused window is on screen, so use pointer location instead */
|
||||
if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
|
||||
for (i = 0; i < n; i++)
|
||||
if (INTERSECT(x, y, 1, 1, info[i]))
|
||||
if( args.mon < 0
|
||||
&& !area
|
||||
&& XQueryPointer(dpy, root, &dw, &dw, &x, &y,
|
||||
&di, &di, &du))
|
||||
for(i = 0; i < n; i++)
|
||||
if(INTERSECT(x, y, 1, 1, info[i]))
|
||||
break;
|
||||
|
||||
x = info[i].x_org;
|
||||
y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
|
||||
y = info[i].y_org + (args.topbar ? 0 : info[i].height - mh);
|
||||
mw = info[i].width;
|
||||
XFree(info);
|
||||
} else
|
||||
#endif
|
||||
#endif /* ifdef XINERAMA */
|
||||
{
|
||||
if (!XGetWindowAttributes(dpy, parentwin, &wa))
|
||||
die("could not get embedding window attributes: 0x%lx",
|
||||
parentwin);
|
||||
if(!XGetWindowAttributes(dpy, parentwin, &wa)){
|
||||
fprintf(stderr,
|
||||
"%s: could not get embedding window"
|
||||
"attributes: 0x%lx\n",
|
||||
argv[0], parentwin);
|
||||
return EX_UNAVAILABLE; /* appropriate sysexit? */
|
||||
}
|
||||
x = 0;
|
||||
y = topbar ? 0 : wa.height - mh;
|
||||
y = args.topbar ? 0 : wa.height - mh;
|
||||
mw = wa.width;
|
||||
}
|
||||
inputw = MIN(inputw, mw/3);
|
||||
|
||||
/* create menu window */
|
||||
swa.override_redirect = True;
|
||||
swa.background_pixel = scheme[Scheme][ColBg].pixel;
|
||||
swa.background_pixel = bg.pixel;
|
||||
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
|
||||
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
|
||||
CopyFromParent, CopyFromParent, CopyFromParent,
|
||||
@ -190,7 +228,7 @@ main(int argc, char *argv[]){
|
||||
|
||||
|
||||
XMapRaised(dpy, win);
|
||||
if (embed) {
|
||||
if (args.embed != NULL) {
|
||||
XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
|
||||
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
|
||||
for (i = 0; i < du && dws[i] != win; ++i)
|
||||
@ -199,6 +237,7 @@ main(int argc, char *argv[]){
|
||||
}
|
||||
}
|
||||
drw_resize(drw, mw, mh);
|
||||
drw_setscheme(drw, fg, bg);
|
||||
|
||||
text[0] = '\0';
|
||||
do{
|
||||
@ -207,7 +246,6 @@ main(int argc, char *argv[]){
|
||||
if(text[i] == '\n')
|
||||
text[i] = '\0';
|
||||
|
||||
drw_setscheme(drw, scheme[Scheme]);
|
||||
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
||||
|
||||
if(*text != '\0')
|
||||
@ -221,11 +259,9 @@ main(int argc, char *argv[]){
|
||||
drw_map(drw, win, 0, 0, mw, mh);
|
||||
}while(
|
||||
fgets(text, (sizeof text) / (sizeof *text), stdin) != NULL
|
||||
|| !BREAK_ON_EOF
|
||||
|| !args.break_on_eof
|
||||
);
|
||||
|
||||
for (i = 0; i < SchemeLast; i++)
|
||||
free(scheme[i]);
|
||||
drw_free(drw);
|
||||
XSync(dpy, False);
|
||||
XCloseDisplay(dpy);
|
||||
|
@ -1,12 +1,16 @@
|
||||
/* See LICENSE file for copyright and license details. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <stdarg.h> /* va_start(3), va_end(3), va_list */
|
||||
#include <stdio.h> /* fputc(3), perror(3) */
|
||||
#include <stdlib.h> /* calloc(3), exit(3) */
|
||||
#include <string.h> /* strlen(3) */
|
||||
#include <X11/Xlib.h> /* Display */
|
||||
#include <X11/Xft/Xft.h>
|
||||
|
||||
#include "drw.h"
|
||||
#include "util.h"
|
||||
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
||||
|
||||
#define UTF_INVALID 0xFFFD
|
||||
#define UTF_SIZ 4
|
||||
@ -16,6 +20,34 @@ static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}
|
||||
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
||||
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
||||
|
||||
void
|
||||
die(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
||||
fputc(' ', stderr);
|
||||
perror(NULL);
|
||||
} else {
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *
|
||||
ecalloc(size_t nmemb, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!(p = calloc(nmemb, size)))
|
||||
die("calloc:");
|
||||
return p;
|
||||
}
|
||||
|
||||
static long
|
||||
utf8decodebyte(const char c, size_t *i)
|
||||
{
|
||||
@ -194,7 +226,7 @@ drw_fontset_free(Fnt *font)
|
||||
}
|
||||
|
||||
void
|
||||
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
drw_clr_create(Drw *drw, XftColor *dest, const char *clrname)
|
||||
{
|
||||
if (!drw || !dest || !clrname)
|
||||
return;
|
||||
@ -205,23 +237,6 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
||||
die("error, cannot allocate color '%s'", clrname);
|
||||
}
|
||||
|
||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
||||
* returned color scheme when done using it. */
|
||||
Clr *
|
||||
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
||||
{
|
||||
size_t i;
|
||||
Clr *ret;
|
||||
|
||||
/* need at least two colors for a scheme */
|
||||
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < clrcount; i++)
|
||||
drw_clr_create(drw, &ret[i], clrnames[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
drw_setfontset(Drw *drw, Fnt *set)
|
||||
{
|
||||
@ -230,18 +245,20 @@ drw_setfontset(Drw *drw, Fnt *set)
|
||||
}
|
||||
|
||||
void
|
||||
drw_setscheme(Drw *drw, Clr *scm)
|
||||
drw_setscheme(Drw *drw, XftColor fg, XftColor bg)
|
||||
{
|
||||
if (drw)
|
||||
drw->scheme = scm;
|
||||
if (drw) {
|
||||
drw->bg = bg;
|
||||
drw->fg = fg;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
||||
{
|
||||
if (!drw || !drw->scheme)
|
||||
if (!drw || !drw->bg || !drw->fg)
|
||||
return;
|
||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->bg.pixel : drw->fg.pixel);
|
||||
if (filled)
|
||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||
else
|
||||
@ -266,13 +283,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||
XftResult result;
|
||||
int charexists = 0;
|
||||
|
||||
if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
|
||||
if (!drw || (render && (!drw->bg || !drw->fg)) || !text || !drw->fonts)
|
||||
return 0;
|
||||
|
||||
if (!render) {
|
||||
w = ~w;
|
||||
} else {
|
||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
||||
XSetForeground(drw->dpy, drw->gc, (invert ? drw->fg : drw->bg).pixel);
|
||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
||||
d = XftDrawCreate(drw->dpy, drw->drawable,
|
||||
DefaultVisual(drw->dpy, drw->screen),
|
||||
@ -322,7 +339,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
|
||||
|
||||
if (render) {
|
||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
||||
XftDrawStringUtf8(d, &(invert ? drw->bg : drw->fg),
|
||||
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
|
||||
}
|
||||
x += ew;
|
||||
|
@ -16,14 +16,16 @@ enum { ColFg, ColBg }; /* Clr scheme index */
|
||||
typedef XftColor Clr;
|
||||
|
||||
typedef struct {
|
||||
unsigned int w, h;
|
||||
XftColor bg;
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Window root;
|
||||
Drawable drawable;
|
||||
GC gc;
|
||||
Clr *scheme;
|
||||
XftColor fg;
|
||||
Fnt *fonts;
|
||||
GC gc;
|
||||
unsigned int h;
|
||||
Window root;
|
||||
int screen;
|
||||
unsigned int w;
|
||||
} Drw;
|
||||
|
||||
/* Drawable abstraction */
|
||||
@ -47,7 +49,7 @@ void drw_cur_free(Drw *drw, Cur *cursor);
|
||||
|
||||
/* Drawing context manipulation */
|
||||
void drw_setfontset(Drw *drw, Fnt *set);
|
||||
void drw_setscheme(Drw *drw, Clr *scm);
|
||||
void drw_setscheme(Drw *drw, XftColor fg, XftColor bg);
|
||||
|
||||
/* Drawing functions */
|
||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
||||
|
@ -1,11 +1,11 @@
|
||||
from json import dumps, loads
|
||||
|
||||
bookmarks = "bookmarks.json"
|
||||
bookmarks_filename = "bookmarks.json"
|
||||
|
||||
def load():
|
||||
with open(bookmarks) as f:
|
||||
with open(bookmarks_filename) as f:
|
||||
return loads(f.read())
|
||||
|
||||
def store(b):
|
||||
with open(bookmarks + ".new", 'w') as f:
|
||||
with open(bookmarks_filename + ".new", 'w') as f:
|
||||
return f.write(dumps(b))
|
||||
|
@ -1 +1,3 @@
|
||||
CFLAGS += -g
|
||||
|
||||
libpsargs.o:
|
||||
|
@ -1,4 +1,10 @@
|
||||
all: lowercase-ascii uppercase-ascii
|
||||
all: lowercase uppercase
|
||||
|
||||
lowercase: lowercase-ascii
|
||||
mv lowercase-ascii lowercase
|
||||
|
||||
uppercase: uppercase-ascii
|
||||
mv uppercase-ascii uppercase
|
||||
|
||||
lowercase-ascii: case.c case-ascii.h
|
||||
$(CC) -DCONV=TOLOWER -include case-ascii.h -o lowercase-ascii case.c
|
||||
|
@ -6,24 +6,19 @@ lowercase \(en make text lowercase
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
lowercase (-f)
|
||||
lowercase
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Lowercase prints text from standard input to standard output as lowercase.
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
|
||||
Lowercase will print an error message and exit with the appropriate status from sysexits(3) if it attempts
|
||||
to process a glyph outside the supported encoding range; this is to not inadverdently mangle multi-byte
|
||||
characters. The -f option exists to override this and process every character anyway.
|
||||
Lowercase prints text from standard input to standard output as lowercase. It
|
||||
passes through text it can't convert.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
Lowercase is not Unicode aware unless it's compiled with the USE_ICU flag, which requires libicu.
|
||||
This isn't tested to any extent.
|
||||
Lowercase is not Unicode aware.
|
||||
.PP
|
||||
Lowercase is redundant to usages of tr(1) among other POSIX-specified utilities.
|
||||
Lowercase is redundant to usages of tr(1) among other POSIX-specified
|
||||
utilities.
|
||||
|
||||
.SH HISTORY
|
||||
|
||||
|
@ -70,13 +70,13 @@ get_memory_usage() {
|
||||
PUBLIC_IP="$(ifpublic)"
|
||||
|
||||
printbar() {
|
||||
printf "%b" "$(get_current_desktop)"
|
||||
# printf "%b" "$(get_current_desktop)"
|
||||
printf "%b" $($DATE)
|
||||
printf "%b" "$DELIMITER"
|
||||
printf "%b" "BAT: $(battery)"
|
||||
printf "%b" "$DELIMITER"
|
||||
printf "%b" "CPU: $(get_cpu_temp)"
|
||||
printf "%b" "$DELIMITER"
|
||||
# printf "%b" "CPU: $(get_cpu_temp)"
|
||||
# printf "%b" "$DELIMITER"
|
||||
printf "%b" "PuIP: $PUBLIC_IP"
|
||||
#printf "%b" "$DELIMITER"
|
||||
#printf "%b" "MEM: $(get_memory_usage)"
|
||||
|
139
niceties/openbsd
Normal file
139
niceties/openbsd
Normal file
@ -0,0 +1,139 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# found this here... may auto install openbsd... may not... who knows
|
||||
|
||||
prog(){ while test -n "$!" # ask your doctor about progesterone
|
||||
do if ! command -v "$1" >/dev/null
|
||||
then printf '%s: %s command not found. Please install it.\n' \
|
||||
"$0" "$1" 1>&2
|
||||
false
|
||||
fi done }
|
||||
|
||||
prog curl
|
||||
if ! prog signify
|
||||
then if prog signify-openbsd
|
||||
then alias signify=signify-openbsd
|
||||
else false
|
||||
fi fi
|
||||
|
||||
OBSD="$HOME"/OpenBSD
|
||||
REL=7.5
|
||||
SREL="$(printf '%s\n' "$REL" | tr -d .)"
|
||||
|
||||
test -n "$ARCH" \
|
||||
|| case "$(uname -m)" in
|
||||
# aarch64) ARCH=arm64 ;;
|
||||
amd64) ARCH=amd64 ;;
|
||||
# arm64) ARCH=arm64 ;;
|
||||
i386) ARCH=i386 ;;
|
||||
# *) ARCH=riscv64 ;;
|
||||
*) ARCH=arm64 ;;
|
||||
esac
|
||||
|
||||
test -n "$MIRROR" \
|
||||
|| MIRROR=ftp://mirrors.mit.edu/pub/OpenBSD
|
||||
|
||||
case "$ARCH" in
|
||||
amd64) QEMU=x86_64 ;;
|
||||
i386) QEMU=i386 ;;
|
||||
*) QEMU=aarch64 ;;
|
||||
esac
|
||||
|
||||
printf '%s: enter a public SSH key for accessing the virtual machine.\n:: ' "$0"
|
||||
PUBSSH="$(head -n 1)"
|
||||
printf "\
|
||||
%s: Setting up a virtualized OpenBSD %s (%s) instance from the mirror %s.
|
||||
%s: Control+C to cancel. Waiting 10s to continue...
|
||||
" "$0" "$REL" "$ARCH" "$MIRROR" \
|
||||
"$0" 1>&2
|
||||
sleep 10
|
||||
|
||||
# <https://www.skreutz.com/posts/autoinstall-openbsd-on-qemu/>
|
||||
|
||||
mkdir -p "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH"
|
||||
curl -O --output-dir "$OBSD"/mirror/pub/OpenBSD/"$REL"/ \
|
||||
https://ftp.openbsd.org/pub/OpenBSD/"$REL"/openbsd-"$SREL"-base.pub
|
||||
|
||||
for f in SHA256.sig bsd bsd.mp bsd.rd pxeboot \
|
||||
base"$SREL".tgz comp"$SREL".tgz man"$SREL".tgz
|
||||
do curl -O --output-dir "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH" \
|
||||
"$MIRROR"/"$REL"/"$ARCH"/"$f"
|
||||
done
|
||||
signify -C -p "$OBSD"/mirror/pub/OpenBSD/"$REL"/openbsd-"$SREL"-base.pub \
|
||||
-x "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH"/SHA256.sig \
|
||||
-- bsd* pxeboot *"$SREL".tgz
|
||||
|
||||
printf "\
|
||||
%s: Using the following autoinstall(8) install.conf:
|
||||
Change the default console to com0 = yes
|
||||
Which speed should com0 use = 115200
|
||||
System hostname = openbsd
|
||||
Password for root = *************
|
||||
Allow root ssh login = no
|
||||
Setup a user = puffy
|
||||
Password for user = *************
|
||||
Public ssh key for user = %s
|
||||
What timezone are you in = UTC
|
||||
Location of sets = http
|
||||
HTTP Server = 10.33.2.1
|
||||
Unable to connect using https. Use http instead = yes
|
||||
URL to autopartitioning template for disklabel = http://10.33.2.1/disklabel
|
||||
Set name(s) = site%s.tgz
|
||||
Checksum test for site%s.tgz failed. Continue anyway = yes
|
||||
Unverified sets: site%s.tgz. Continue without verification = yes
|
||||
" "$0" "$PUBSSH" "$SREL" "$SREL" "$SREL" \
|
||||
| tee -a /dev/stderr \
|
||||
| sed -e 1d -e 's:^\t::g' \
|
||||
>"$OBSD"/mirror/install.conf
|
||||
|
||||
printf "\
|
||||
%s: Using the following disklabel(8) template:
|
||||
/ 8G
|
||||
swap 256M
|
||||
" "$0" \
|
||||
| tee -a /dev/stderr \
|
||||
| sed -e 1d -e 's:^\t::g' \
|
||||
>"$OBSD"/mirror/disklabel
|
||||
|
||||
mkdir -p site
|
||||
printf "\
|
||||
#!/bin/sh
|
||||
printf 'https://cdn.openbsd.org/pub/OpenBSD\n' \
|
||||
>/etc/installurl
|
||||
printf 'permit keepenv nopass :wheel\n' \
|
||||
>>/etc/doas.conf
|
||||
" >"$OBSD"/site/install.site
|
||||
chmod +x "$OBSD"/site/install.site
|
||||
tar -C site czf "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH"/site"$SREL".tgz
|
||||
# probably not necessary
|
||||
#ls -l "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH" >"$OBSD"/index.txt
|
||||
|
||||
mkdir -p tftp/etc
|
||||
ln "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH"/pxeboot "$OBSD"/tftp/auto_install
|
||||
ln "$OBSD"/mirror/pub/OpenBSD/"$REL"/"$ARCH"/bsd.rd "$OBSD"/tftp/bsd.rd
|
||||
printf "\
|
||||
stty com0 115200
|
||||
set tty com0
|
||||
boot tftp:/bsd.rd
|
||||
" >"$OBSD"/tftp/etc/boot.conf
|
||||
|
||||
qemu-img create -f qcow2 "$OBSD"/hd0.qcow2 9G
|
||||
|
||||
chmod +x
|
||||
|
||||
python3 -m http.server --directory "$OBSD"/mirror --bind 127.0.0.1 8080 &
|
||||
|
||||
qemu-system-"$QEMU" \
|
||||
-drive file=\"\$OBSD\"/hd0.qcow2,media=disk,if=virtio \
|
||||
-device e1000,netdev=n1 \
|
||||
-m 512M \
|
||||
-netdev user,id=n1,hostname=openbsd-vm,tftp-server-name=10.0.2.1,tftp=tftp,bootfile=auto_install,hostfwd=tcp::2222-:22,guestfwd=tcp:10.0.2.1:80-cmd:socat STDIO TCP4:127.0.0.1:8080 \
|
||||
-nographic &
|
||||
|
||||
printf "\
|
||||
%s: ssh into puffy@127.0.0.1:2222 to connect.
|
||||
%s: press Enter to quit.
|
||||
" "$0" "$0" 1>&2
|
||||
head -n 1
|
@ -4,7 +4,7 @@
|
||||
# Not a great use of disk...
|
||||
dd 2>/dev/null \
|
||||
| sed \
|
||||
-e 's/l/w/g' \
|
||||
-e 's/r/w/g' \
|
||||
-e 's/smaww/smol/g' \
|
||||
-e 's/wove/wuv/g'
|
||||
-e s/l/w/g \
|
||||
-e s/r/w/g \
|
||||
-e s/smaww/smol/g \
|
||||
-e s/wove/wuv/g
|
||||
|
@ -52,7 +52,7 @@ case "$1" in
|
||||
-) "$0" r -"$2" ;;
|
||||
|
||||
a*)
|
||||
str isvalue $2 && ! str isvalue $3 && str isdigit "$2" \
|
||||
test -n $2 && ! str isvalue $3 && str isdigit "$2" \
|
||||
|| usage
|
||||
"$0".$VOLUME_SYSTEM "$@"
|
||||
;;
|
||||
|
119
npc.rs
Normal file
119
npc.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2023 DTB <trinity@trinity.moe>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
env::args,
|
||||
io::{ stdin, stdout, Error, Read, Write },
|
||||
process::ExitCode
|
||||
};
|
||||
|
||||
extern crate getopt;
|
||||
use getopt::{ Opt, Parser };
|
||||
|
||||
extern crate sysexits;
|
||||
use sysexits::{ EX_OK, EX_OSERR, EX_USAGE };
|
||||
|
||||
fn oserr(s: &str, e: Error) -> ExitCode {
|
||||
eprintln!("{}: {}", s, e);
|
||||
ExitCode::from(EX_OSERR as u8)
|
||||
}
|
||||
|
||||
fn usage(s: &str) -> ExitCode {
|
||||
eprintln!("Usage: {} (-aet)", s);
|
||||
ExitCode::from(EX_USAGE as u8)
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let argv = args().collect::<Vec<String>>();
|
||||
let input = stdin();
|
||||
let mut output = stdout().lock();
|
||||
|
||||
let mut opts = Parser::new(&argv, "7et");
|
||||
let mut ascii = false;
|
||||
let mut showend = false;
|
||||
let mut showtab = false;
|
||||
|
||||
loop {
|
||||
match opts.next() {
|
||||
None => break,
|
||||
Some(o) =>
|
||||
match o {
|
||||
Ok(Opt('7', None)) => ascii = true,
|
||||
Ok(Opt('e', None)) => showend = true,
|
||||
Ok(Opt('t', None)) => showtab = true,
|
||||
_ => { return usage(&argv[0]); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cat -v emulation */
|
||||
if ascii {
|
||||
let mut c: u8 = 0;
|
||||
|
||||
for r in input.bytes() {
|
||||
match r {
|
||||
Ok(v) => { c = v; },
|
||||
Err(e) => { return oserr(&argv[0], e); }
|
||||
}
|
||||
/* If a given byte isn't expressable in ASCII, print "M-[char]",
|
||||
* where char is the chosen representation of the byte with its
|
||||
* high bit set to 0. */
|
||||
if c & 0x80 /* 0b 1000 0000 */ != 0 { print!("M-"); }
|
||||
c ^= 0x80;
|
||||
|
||||
/* ASCII DEL is represented as ^? */
|
||||
if c == 0x7f as u8 {
|
||||
if let Err(e) = output.write_all(b"^?") {
|
||||
return oserr(&argv[0], e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if c == '\n' as u8 && showend {
|
||||
if let Err(e) = output.write_all(b"$") {
|
||||
return oserr(&argv[0], e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ASCII visual characters are shown literally. */
|
||||
if c >= ' ' as u8 || c == '\n' as u8
|
||||
|| (!showtab && c == '\t' as u8) {
|
||||
if let Err(e) = output.write_all(&[c]) {
|
||||
return oserr(&argv[0], e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, characters are shown as their control code, with NUL
|
||||
* being ^@ and successive characters shown as "^" catenated with
|
||||
* successive visual characters past "@". */
|
||||
else {
|
||||
c += '@' as u8;
|
||||
if let Err(e) = output.write_all(b"^") {
|
||||
return oserr(&argv[0], e);
|
||||
}
|
||||
if let Err(e) = output.write_all(&[c]) {
|
||||
return oserr(&argv[0], e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("not implemented");
|
||||
}
|
||||
|
||||
ExitCode::from(EX_OK as u8)
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#include <fcntl.h> /* open(2), O_RDONLY */
|
||||
#include <stdio.h> /* fprintf(3), perror(3) */
|
||||
#if !defined EX_OK || !defined EX_OSERR || !defined EX_USAGE
|
||||
#if !defined EX_OSERR || !defined EX_USAGE
|
||||
# include <sysexits.h>
|
||||
#endif
|
||||
#include <unistd.h> /* dup(2), dup2(2), fork(2), STDIN_FILENO */
|
||||
|
122
walk/walk.rs
Normal file
122
walk/walk.rs
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2024 DTB <trinity@trinity.moe>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*
|
||||
* This file incorporates work covered by the following copyright and permission
|
||||
* notice:
|
||||
*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
env::{args, current_dir},
|
||||
fs::{read_dir, DirEntry},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
extern crate getopt;
|
||||
use getopt::{Opt, Parser};
|
||||
|
||||
extern crate sysexits;
|
||||
use sysexits::{EX_SOFTWARE, EX_USAGE};
|
||||
|
||||
enum Terminator {
|
||||
USER,
|
||||
NUL,
|
||||
NEWL,
|
||||
ASV,
|
||||
}
|
||||
|
||||
/* Recursively walks d, yielding all contained files and folders. */
|
||||
fn walk(d: &Path, l: i8) -> impl Iterator<Item = DirEntry> {
|
||||
assert!(d.is_dir());
|
||||
|
||||
// TODO: read_dir(d)??
|
||||
for entry in read_dir(d)? {
|
||||
let e = entry?;
|
||||
yield e;
|
||||
if e.is_dir() {
|
||||
for f in walk(e.path(), l - 1)? {
|
||||
yield f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn usage(s: &str) -> ExitCode {
|
||||
eprintln!("Usage: {} (-0n) (-d [delimiter]) (-l [levels])", s);
|
||||
ExitCode::from(EX_USAGE as u8)
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let argv = args().collect::<Vec<String>>();
|
||||
|
||||
let mut opts = Parser::new(&argv, "0d:l:nq");
|
||||
let mut levels: i8 = -1;
|
||||
let mut t: (Terminator, Option<String>) = (ASV, None);
|
||||
|
||||
loop {
|
||||
match opts.next() {
|
||||
None => break,
|
||||
Some(opt) => match opt {
|
||||
Ok(Opt('0', None)) => t = (NUL, None),
|
||||
Ok(Opt('n', None)) => t = (NEWL, None),
|
||||
Ok(Opt('d', Some(arg))) => t = (USER, arg),
|
||||
Ok(Opt('l', Some(arg))) => match arg.parse::<u8>() {
|
||||
Ok(l) => levels = l,
|
||||
_ => {
|
||||
return usage(&argv[0]);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return usage(&argv[0]);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
/* t.2 can only be Some if t.1 is USER */
|
||||
assert_eq!(t.1 == USER, !t.2.is_none());
|
||||
|
||||
// if(*argv == NULL)
|
||||
// argv = dot;
|
||||
//
|
||||
// {
|
||||
// int retval;
|
||||
//
|
||||
// for(retval = 0; *argv != NULL; ++argv)
|
||||
// if((retval = walk(*argv, levels, verbosity >= 2 ? argv0 : NULL))
|
||||
// != EX_OK){
|
||||
// if(verbosity >= 1)
|
||||
// fprintf(stderr, "%s: %s: %s\n",
|
||||
// argv0, *argv, strerror(errno));
|
||||
// return retval;
|
||||
// }
|
||||
// }
|
||||
|
||||
EX_OK as u8
|
||||
}
|
Loading…
Reference in New Issue
Block a user