From 17f417f519b9d0febc181466039854f851790f50 Mon Sep 17 00:00:00 2001 From: Alexey Frunze Date: Fri, 9 May 2014 23:53:52 -0700 Subject: [PATCH 01/40] C compiler improvements Fix malloc(0) issue (#26) in cpp. Reduce cpp size and allow for larger inputs. Clean up unused variables in Smaller C. --- src/cmd/cpp/Makefile | 5 +- src/cmd/cpp/cpp.c | 6 +- src/cmd/cpp/doprnt.c | 203 ++++++++++++++++++++++++++++++++++++++++++ src/cmd/smlrc/smlrc.c | 6 +- 4 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 src/cmd/cpp/doprnt.c diff --git a/src/cmd/cpp/Makefile b/src/cmd/cpp/Makefile index 5467708..80a3036 100644 --- a/src/cmd/cpp/Makefile +++ b/src/cmd/cpp/Makefile @@ -3,14 +3,15 @@ include $(TOPSRC)/target.mk #include $(TOPSRC)/cross.mk #CFLAGS = -DCROSS -OBJS = cpp.o cpy.o token.o +OBJS = cpp.o cpy.o token.o doprnt.o MAN = cpp.0 MANSRC = cpp.1 LDFLAGS += -g CFLAGS += -Werror -Wall -Os -CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC +#CFLAGS += -DCPP_DEBUG -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC +CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC all: cpp $(MAN) diff --git a/src/cmd/cpp/cpp.c b/src/cmd/cpp/cpp.c index 94ca6f7..59b4141 100644 --- a/src/cmd/cpp/cpp.c +++ b/src/cmd/cpp/cpp.c @@ -1309,6 +1309,7 @@ expdef(const uchar *vp, struct recur *rp, int gotwarn) uchar *sptr; int narg, c, i, plev, snuff, instr; int ellips = 0, shot = gotwarn; + size_t allocsz; DPRINT(("expdef rp %s\n", (rp ? (const char *)rp->sp->namep : ""))); c = sloscan(); @@ -1321,7 +1322,10 @@ expdef(const uchar *vp, struct recur *rp, int gotwarn) } else narg = vp[1]; - args = malloc(sizeof(uchar *) * (narg+ellips)); + // The code depends on malloc(0) returning a non-NULL pointer, which is not guaranteed. + // Workaround it. + allocsz = sizeof(uchar *) * ((narg+ellips) ? (narg+ellips) : 1); + args = malloc(allocsz); if (args == NULL) error("expdef: out of mem"); diff --git a/src/cmd/cpp/doprnt.c b/src/cmd/cpp/doprnt.c new file mode 100644 index 0000000..c5ed28d --- /dev/null +++ b/src/cmd/cpp/doprnt.c @@ -0,0 +1,203 @@ +/* +Copyright (c) 2013, Alexey Frunze +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +#include +#include +#include + +int _doprnt (char const *fmt, va_list pp, FILE *stream) +{ + int cnt = 0; + const char* p; + const char* phex = "0123456789abcdef"; + char s[1/*sign*/+10/*magnitude*/+1/*\0*/]; // up to 11 octal digits in 32-bit numbers + char* pc; + int n, sign, msign; + int minlen = 0, len; + int leadchar; + + for (p = fmt; *p != '\0'; p++) + { + if (*p != '%' || p[1] == '%') + { + fputc(*p, stream); + p = p + (*p == '%'); + cnt++; + continue; + } + p++; + minlen = 0; + msign = 0; + if (*p == '+') { msign = 1; p++; } + else if (*p == '-') { msign = -1; p++; } + leadchar = ' '; + if (*p >= '0' && *p <= '9') + { + if (*p == '0') + leadchar = '0'; + while (*p >= '0' && *p <= '9') + minlen = minlen * 10 + *p++ - '0'; + if (msign < 0) + minlen = -minlen; + msign = 0; + } + if (!msign) + { + if (*p == '+') { msign = 1; p++; } + else if (*p == '-') { msign = -1; p++; } + } + switch (*p) + { + case 'c': + while (minlen > 1) { fputc(' ', stream); cnt++; minlen--; } + fputc(va_arg(pp, int), stream); + while (-minlen > 1) { fputc(' ', stream); cnt++; minlen++; } + cnt++; + break; + case 's': + pc = va_arg(pp, char*); + len = 0; + if (pc) + len = strlen(pc); + while (minlen > len) { fputc(' ', stream); cnt++; minlen--; } + if (len) + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'i': + case 'd': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + sign = 1 - 2 * (n < 0); + do + { + *--pc = '0' + (n - n / 10 * 10) * sign; + n = n / 10; + len++; + } while (n); + if (sign < 0) + { + *--pc = '-'; + len++; + } + else if (msign > 0) + { + *--pc = '+'; + len++; + msign = 0; + } + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'u': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + unsigned nn = n; + *--pc = '0' + nn % 10; + n = nn / 10; + len++; + } while (n); + if (msign > 0) + { + *--pc = '+'; + len++; + msign = 0; + } + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'X': + phex = "0123456789ABCDEF"; + // fallthrough + case 'p': + case 'x': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + *--pc = phex[n & 0xF]; + n = (n >> 4) & ((1 << (8 * sizeof n - 4)) - 1); // drop sign-extended bits + len++; + } while (n); + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + case 'o': + pc = &s[sizeof s - 1]; + *pc = '\0'; + len = 0; + n = va_arg(pp, int); + do + { + *--pc = '0' + (n & 7); + n = (n >> 3) & ((1 << (8 * sizeof n - 3)) - 1); // drop sign-extended bits + len++; + } while (n); + while (minlen > len) { fputc(leadchar, stream); cnt++; minlen--; } + while (*pc != '\0') + { + fputc(*pc++, stream); + cnt++; + } + while (-minlen > len) { fputc(' ', stream); cnt++; minlen++; } + break; + default: + return -1; + } + } + + return cnt; +} diff --git a/src/cmd/smlrc/smlrc.c b/src/cmd/smlrc/smlrc.c index 987bcd2..87360b7 100644 --- a/src/cmd/smlrc/smlrc.c +++ b/src/cmd/smlrc/smlrc.c @@ -6401,7 +6401,6 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) int hasInit = tok == '='; int needsGlobalInit = isGlobal & !external; int sz = GetDeclSize(lastSyntaxPtr, 0); - int localAllocSize = 0; int skipLabel = 0; int initLabel = 0; @@ -6525,7 +6524,6 @@ int ParseDecl(int tok, unsigned structInfo[4], int cast, int label) // update its offset in the offset token SyntaxStack[lastSyntaxPtr + 1][1] = CurFxnLocalOfs; - localAllocSize = oldOfs - CurFxnLocalOfs; if (CurFxnMinLocalOfs > CurFxnLocalOfs) CurFxnMinLocalOfs = CurFxnLocalOfs; @@ -6878,7 +6876,9 @@ void AddFxnParamSymbols(int SyntaxPtr) if (tok == tokIdent) { int sz; +#ifndef NO_ANNOTATIONS int paramPtr; +#endif if (i + 1 >= SyntaxStackCnt) //error("Internal error: AddFxnParamSymbols(): Invalid input\n"); @@ -6896,7 +6896,9 @@ void AddFxnParamSymbols(int SyntaxPtr) // Let's calculate this parameter's relative on-stack location CurFxnParamOfs = (CurFxnParamOfs + SizeOfWord - 1) / SizeOfWord * SizeOfWord; +#ifndef NO_ANNOTATIONS paramPtr = SyntaxStackCnt; +#endif PushSyntax2(SyntaxStack[i][0], SyntaxStack[i][1]); PushSyntax2(tokLocalOfs, CurFxnParamOfs); CurFxnParamOfs += sz; From a0d4e7f517f7ad4e77d21f4144a4e8cac458bb62 Mon Sep 17 00:00:00 2001 From: Sergey Date: Mon, 12 May 2014 23:52:09 -0700 Subject: [PATCH 02/40] Initialization of interrupt controller simplified.. --- sys/pic32/machdep.c | 46 ++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/sys/pic32/machdep.c b/sys/pic32/machdep.c index 6ae6c9b..bf4cf1e 100644 --- a/sys/pic32/machdep.c +++ b/sys/pic32/machdep.c @@ -194,22 +194,38 @@ startup() */ INTCON = 0; /* Interrupt Control */ IPTMR = 0; /* Temporal Proximity Timer */ - IFS(0) = - PIC32_IPC_IP0(2) | PIC32_IPC_IP1(1) | - PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | - PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | - PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; - IFS(1) = IFS(2) = 0; /* Interrupt Flag Status */ - IEC(0) = IEC(1) = IEC(2) = 0; /* Interrupt Enable Control */ - IPC(0) = IPC(1) = IPC(2) = IPC(3) = /* Interrupt Priority Control */ - IPC(4) = IPC(5) = IPC(6) = IPC(7) = - IPC(8) = IPC(9) = IPC(10) = IPC(11) = - IPC(12) = - PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) | - PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | - PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | - PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + /* Interrupt Flag Status */ + IFS(0) = PIC32_IPC_IP0(2) | PIC32_IPC_IP1(1) | + PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | + PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | + PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + IFS(1) = 0; + IFS(2) = 0; + + /* Interrupt Enable Control */ + IEC(0) = 0; + IEC(1) = 0; + IEC(2) = 0; + + /* Interrupt Priority Control */ + unsigned ipc = PIC32_IPC_IP0(1) | PIC32_IPC_IP1(1) | + PIC32_IPC_IP2(1) | PIC32_IPC_IP3(1) | + PIC32_IPC_IS0(0) | PIC32_IPC_IS1(0) | + PIC32_IPC_IS2(0) | PIC32_IPC_IS3(0) ; + IPC(0) = ipc; + IPC(1) = ipc; + IPC(2) = ipc; + IPC(3) = ipc; + IPC(4) = ipc; + IPC(5) = ipc; + IPC(6) = ipc; + IPC(7) = ipc; + IPC(8) = ipc; + IPC(9) = ipc; + IPC(10) = ipc; + IPC(11) = ipc; + IPC(12) = ipc; /* * Setup wait states. From e725ab2b44889b31b0f664434d15ff1bd4f8a2f5 Mon Sep 17 00:00:00 2001 From: Alexey Frunze Date: Wed, 14 May 2014 02:49:38 -0700 Subject: [PATCH 03/40] Update cpp to pcc 1.0.0's cpp Update the preprocessor to fix some of its bugs. --- src/cmd/cpp/Makefile | 10 +- src/cmd/cpp/compat.c | 91 +++ src/cmd/cpp/compat.h | 14 + src/cmd/cpp/config.h | 11 + src/cmd/cpp/cpp.c | 1654 +++++++++++++++++++++----------------- src/cmd/cpp/cpp.h | 137 ++-- src/cmd/cpp/cpy.y | 3 + src/cmd/cpp/scanner.l | 939 ++++++++++++++++++++++ src/cmd/cpp/tests/res11 | 22 + src/cmd/cpp/tests/res12 | 21 + src/cmd/cpp/tests/res13 | 13 + src/cmd/cpp/tests/res2 | 3 +- src/cmd/cpp/tests/test11 | 20 + src/cmd/cpp/tests/test12 | 19 + src/cmd/cpp/tests/test13 | 11 + src/cmd/cpp/token.c | 363 +++++---- 16 files changed, 2384 insertions(+), 947 deletions(-) create mode 100644 src/cmd/cpp/compat.c create mode 100644 src/cmd/cpp/compat.h create mode 100644 src/cmd/cpp/config.h create mode 100644 src/cmd/cpp/scanner.l create mode 100644 src/cmd/cpp/tests/res11 create mode 100644 src/cmd/cpp/tests/res12 create mode 100644 src/cmd/cpp/tests/res13 create mode 100644 src/cmd/cpp/tests/test11 create mode 100644 src/cmd/cpp/tests/test12 create mode 100644 src/cmd/cpp/tests/test13 diff --git a/src/cmd/cpp/Makefile b/src/cmd/cpp/Makefile index 80a3036..6091894 100644 --- a/src/cmd/cpp/Makefile +++ b/src/cmd/cpp/Makefile @@ -3,7 +3,7 @@ include $(TOPSRC)/target.mk #include $(TOPSRC)/cross.mk #CFLAGS = -DCROSS -OBJS = cpp.o cpy.o token.o doprnt.o +OBJS = cpp.o cpy.o token.o compat.o doprnt.o MAN = cpp.0 MANSRC = cpp.1 @@ -31,7 +31,7 @@ install: all install cpp $(DESTDIR)/bin/ cp cpp.0 $(DESTDIR)/share/man/cat1/ -cpp.o: cpp.c y.tab.h +cpp.o: cpp.c cpp.h y.tab.h config.h .l.o: $(LEX) $(LFLAGS) $< @@ -62,3 +62,9 @@ test: cmp tests/run9 tests/res9 ./cpp < tests/test10 > tests/run10 cmp tests/run10 tests/res10 + ./cpp < tests/test11 > tests/run11 + cmp tests/run11 tests/res11 + ./cpp < tests/test12 > tests/run12 + cmp tests/run12 tests/res12 + ./cpp < tests/test13 > tests/run13 + cmp tests/run13 tests/res13 diff --git a/src/cmd/cpp/compat.c b/src/cmd/cpp/compat.c new file mode 100644 index 0000000..e01786d --- /dev/null +++ b/src/cmd/cpp/compat.c @@ -0,0 +1,91 @@ +/* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ +/* + * Copyright (c) 1998, 2003-2005, 2010-2011, 2013 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" +#include + +#ifndef HAVE_STRLCAT +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return dlen + strlen(s); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return dlen + (s - src); /* count does not include NUL */ +} +#endif /* HAVE_STRLCAT */ + +#ifndef HAVE_STRLCPY +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0 && --n != 0) { + do { + if ((*d++ = *s++) == 0) + break; + } while (--n != 0); + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return s - src - 1; /* count does not include NUL */ +} +#endif /* HAVE_STRLCPY */ diff --git a/src/cmd/cpp/compat.h b/src/cmd/cpp/compat.h new file mode 100644 index 0000000..6d9e654 --- /dev/null +++ b/src/cmd/cpp/compat.h @@ -0,0 +1,14 @@ +#ifndef COMPAT_H__ +#define COMPAT_H__ + +#include + +#ifndef HAVE_STRLCPY +size_t strlcpy(char* dst, const char* src, size_t size); +#endif + +#ifndef HAVE_STRLCAT +size_t strlcat(char* dst, const char* src, size_t size); +#endif + +#endif // COMPAT_H__ diff --git a/src/cmd/cpp/config.h b/src/cmd/cpp/config.h new file mode 100644 index 0000000..b5d0468 --- /dev/null +++ b/src/cmd/cpp/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_H__ +#define CONFIG_H__ + +#define VERSSTR "cpp for RetroBSD" + +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_WAIT_H 1 +//#define HAVE_STRLCPY 1 +//#define HAVE_STRLCAT 1 + +#endif // CONFIG_H__ diff --git a/src/cmd/cpp/cpp.c b/src/cmd/cpp/cpp.c index 59b4141..7a14424 100644 --- a/src/cmd/cpp/cpp.c +++ b/src/cmd/cpp/cpp.c @@ -1,8 +1,6 @@ +/* $Id: cpp.c,v 1.124.2.2 2011/03/27 13:17:19 ragge Exp $ */ + /* - * The C preprocessor. - * This code originates from the V6 preprocessor with some additions - * from V7 cpp, and at last ansi/c99 support. - * * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * @@ -26,32 +24,46 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -# include -#else -# include -# include -# include + +/* + * The C preprocessor. + * This code originates from the V6 preprocessor with some additions + * from V7 cpp, and at last ansi/c99 support. + */ + +#include "config.h" + +#ifdef HAVE_SYS_WAIT_H +#include #endif +#include #include +#ifdef HAVE_UNISTD_H #include +#endif +#include #include +#include +#include +#include +#include +#include "compat.h" #include "cpp.h" #include "y.tab.h" -#define MAXARG 20 /* # of args to a macro, limited by char value */ -#define SBSIZE (12*1024) +struct includ *ifiles; +int slow; /* scan slowly for new tokens */ -static uchar sbf[SBSIZE]; +#define SBSIZE (12*1024)//1000000 + +static usch sbf[SBSIZE]; /* C command */ int tflag; /* traditional cpp syntax */ -#ifdef CPP_DEBUG int dflag; /* debug printouts */ +#ifdef CPP_DEBUG #define DPRINT(x) if (dflag) printf x #define DDPRINT(x) if (dflag > 1) printf x #else @@ -59,26 +71,18 @@ int dflag; /* debug printouts */ #define DDPRINT(x) #endif -#define GCC_VARI - int ofd; -uchar outbuf[CPPBUF]; +usch outbuf[CPPBUF]; int obufp, istty; int Cflag, Mflag, dMflag, Pflag; -uchar *Mfile; +usch *Mfile; struct initar *initar; -int readmac; - -/* avoid recursion */ -struct recur { - struct recur *next; - struct symtab *sp; -}; +int readmac, lastoch; /* include dirs */ struct incs { struct incs *next; - uchar *dir; + usch *dir; dev_t dev; ino_t ino; } *incdir[2]; @@ -87,11 +91,12 @@ struct incs { static struct symtab *filloc; static struct symtab *linloc; +static struct symtab *pragloc; int trulvl; int flslvl; int elflvl; int elslvl; -uchar *stringbuf = sbf; +usch *stringbuf = sbf; /* * Macro replacement list syntax: @@ -100,7 +105,7 @@ uchar *stringbuf = sbf; * character WARN followed by the argument number. * - The value element points to the end of the string, to simplify * pushback onto the input queue. - * + * * The first character (from the end) in the replacement list is * the number of arguments: * VARG - ends with ellipsis, next char is argcount without ellips. @@ -111,74 +116,31 @@ uchar *stringbuf = sbf; * WARN is used: * - in stored replacement lists to tell that an argument comes * - When expanding replacement lists to tell that the list ended. + * + * To ensure that an already expanded identifier won't get expanded + * again a EBLOCK char + its number is stored directly before any + * expanded identifier. */ -#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ -#define VARG 0xfe /* has varargs */ -#define OBJCT 0xff -#define WARN 1 /* SOH, not legal char */ -#define CONC 2 /* STX, not legal char */ -#define SNUFF 3 /* ETX, not legal char */ -#define NOEXP 4 /* EOT, not legal char */ -#define EXPAND 5 /* ENQ, not legal char */ - /* args for lookup() */ #define FIND 0 #define ENTER 1 -static void expdef(const uchar *proto, struct recur *, int gotwarn); +static int readargs(struct symtab *sp, const usch **args); +void prline(const usch *s); +static void prrep(const usch *s); +static void exparg(int); +static void subarg(struct symtab *sp, const usch **args, int); void define(void); -static int canexpand(struct recur *, struct symtab *np); void include(void); void include_next(void); void line(void); void flbuf(void); void usage(void); +usch *xstrdup(const usch *str); static void addidir(char *idir, struct incs **ww); - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -static size_t -my_strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -static uchar * -xstrdup(const char *str) -{ - size_t len = strlen(str)+1; - uchar *rv; - - rv = malloc(len); - if (! rv) - error("xstrdup: out of mem"); - my_strlcpy((char *)rv, str, len); - return rv; -} +void imp(const char *); +#define IMP(x) if (dflag>1) imp(x) int main(int argc, char **argv) @@ -186,7 +148,7 @@ main(int argc, char **argv) struct initar *it; struct symtab *nl; register int ch; - const uchar *fn1, *fn2; + const usch *fn1, *fn2; #ifdef TIMING struct timeval t1, t2; @@ -204,8 +166,7 @@ main(int argc, char **argv) case 'U': /* undef */ case 'D': /* define something */ /* XXX should not need malloc() here */ - it = malloc(sizeof(struct initar)); - if (it == NULL) + if ((it = malloc(sizeof(struct initar))) == NULL) error("couldn't apply -%c %s", ch, optarg); it->type = ch; it->str = optarg; @@ -254,48 +215,59 @@ main(int argc, char **argv) argc -= optind; argv += optind; - filloc = lookup((const uchar *)"__FILE__", ENTER); - linloc = lookup((const uchar *)"__LINE__", ENTER); - filloc->value = linloc->value = (const uchar *)""; /* Just something */ + filloc = lookup((const usch *)"__FILE__", ENTER); + linloc = lookup((const usch *)"__LINE__", ENTER); + filloc->value = linloc->value = stringbuf; + savch(OBJCT); + + /* create a complete macro for pragma */ + pragloc = lookup((const usch *)"_Pragma", ENTER); + savch(0); + savstr((const usch *)"_Pragma("); + savch(0); + savch(WARN); + savch(')'); + pragloc->value = stringbuf; + savch(1); if (tflag == 0) { time_t t = time(NULL); - uchar *n = (uchar *)ctime(&t); + usch *n = (usch *)ctime(&t); /* * Manually move in the predefined macros. */ - nl = lookup((const uchar *)"__TIME__", ENTER); + nl = lookup((const usch *)"__TIME__", ENTER); savch(0); savch('"'); n[19] = 0; savstr(&n[11]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__DATE__", ENTER); + nl = lookup((const usch *)"__DATE__", ENTER); savch(0); savch('"'); n[24] = n[11] = 0; savstr(&n[4]); savstr(&n[20]); savch('"'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC__", ENTER); + nl = lookup((const usch *)"__STDC__", ENTER); savch(0); savch('1'); savch(OBJCT); nl->value = stringbuf-1; - nl = lookup((const uchar *)"__STDC_VERSION__", ENTER); - savch(0); savstr((const uchar *)"199901L"); savch(OBJCT); + nl = lookup((const usch *)"__STDC_VERSION__", ENTER); + savch(0); savstr((const usch *)"199901L"); savch(OBJCT); nl->value = stringbuf-1; } if (Mflag && !dMflag) { - uchar *c; + usch *c; if (argc < 1) error("-M and no infile"); - if ((c = (uchar *)strrchr(argv[0], '/')) == NULL) - c = (uchar *)argv[0]; + if ((c = (usch *)strrchr(argv[0], '/')) == NULL) + c = (usch *)argv[0]; else c++; Mfile = stringbuf; savstr(c); savch(0); - if ((c = (uchar *)strrchr((char *)Mfile, '.')) == NULL) + if ((c = (usch *)strrchr((char *)Mfile, '.')) == NULL) error("-M and no extension: "); c[1] = 'o'; c[2] = 0; @@ -309,10 +281,10 @@ main(int argc, char **argv) istty = isatty(ofd); if (argc && strcmp(argv[0], "-")) { - fn1 = fn2 = (uchar *)argv[0]; + fn1 = fn2 = (usch *)argv[0]; } else { fn1 = NULL; - fn2 = (const uchar *)""; + fn2 = (const usch *)""; } if (pushfile(fn1, fn2, 0, NULL)) error("cannot open %s", argv[0]); @@ -350,126 +322,20 @@ addidir(char *idir, struct incs **ww) return; ww = &w->next; } - w = calloc(sizeof(struct incs), 1); - if (w == NULL) + if ((w = calloc(sizeof(struct incs), 1)) == NULL) error("couldn't add path %s", idir); - w->dir = (uchar *)idir; + w->dir = (usch *)idir; w->dev = st.st_dev; w->ino = st.st_ino; *ww = w; } -uchar * -gotident(struct symtab *nl) -{ - struct symtab *thisnl; - uchar *osp, *ss2, *base; - int c; - - thisnl = NULL; - readmac++; - base = osp = stringbuf; - goto found; - - while ((c = sloscan()) != 0) { - switch (c) { - case IDENT: - if (flslvl) - break; - osp = stringbuf; - - DPRINT(("IDENT0: %s\n", yytext)); - nl = lookup((uchar *)yytext, FIND); - if (nl == 0 || thisnl == 0) - goto found; - if (thisnl == nl) { - nl = 0; - goto found; - } - ss2 = stringbuf; - if ((c = sloscan()) == WSPACE) { - savstr((uchar *)yytext); - c = sloscan(); - } - if (c != EXPAND) { - unpstr((const uchar *)yytext); - if (ss2 != stringbuf) - unpstr(ss2); - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; /* ignore */ - } else { - thisnl = NULL; - if (nl->value[0] == OBJCT) { - unpstr(nl->namep); - (void)sloscan(); /* get yytext correct */ - nl = 0; - } - } - stringbuf = ss2; - -found: if (nl == 0 || subst(nl, NULL) == 0) { - if (nl) - savstr(nl->namep); - else - savstr((uchar *)yytext); - } else if (osp != stringbuf) { - DPRINT(("IDENT1: unput osp %p stringbuf %p\n", - osp, stringbuf)); - ss2 = stringbuf; - cunput(EXPAND); - while (ss2 > osp) - cunput(*--ss2); - thisnl = nl; - stringbuf = osp; /* clean up heap */ - } - break; - - case EXPAND: - DPRINT(("EXPAND!\n")); - thisnl = NULL; - break; - - case CMNT: - getcmnt(); - break; - - case '\n': - /* sloscan() will not eat */ - (void)cinput(); - savch(c); - break; - - case STRING: - case NUMBER: - case WSPACE: - savstr((uchar *)yytext); - break; - - default: - if (c < 256) - savch(c); - else - savstr((uchar *)yytext); - break; - } - if (thisnl == NULL) { - readmac--; - savch(0); - return base; - } - } - error("premature EOF"); - /* NOTREACHED */ - return NULL; /* XXX gcc */ -} - void line() { - static uchar *lbuf; + static usch *lbuf; static int llen; - uchar *p; + usch *p; int c; if ((c = yylex()) != NUMBER) @@ -482,7 +348,7 @@ line() if (c != STRING) goto bad; - p = (uchar *)yytext; + p = (usch *)yytext; if (*p == 'L') p++; c = strlen((char *)p); @@ -493,7 +359,7 @@ line() llen = c; } p[strlen((char *)p)-1] = 0; - if (my_strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) + if (strlcpy((char *)lbuf, (char *)&p[1], SBSIZE) >= SBSIZE) error("line exceeded buffer size"); ifiles->fname = lbuf; @@ -508,17 +374,19 @@ bad: error("bad line directive"); * Return 1 on success. */ static int -fsrch(const uchar *fn, int idx, struct incs *w) +fsrch(const usch *fn, int idx, struct incs *w) { - for (; idx <= SYSINC; idx++) { - if (idx == SYSINC) - w = incdir[SYSINC]; + int i; + + for (i = idx; i < 2; i++) { + if (i > idx) + w = incdir[i]; for (; w; w = w->next) { - uchar *nm = stringbuf; + usch *nm = stringbuf; savstr(w->dir); savch('/'); savstr(fn); savch(0); - if (pushfile(nm, fn, idx, w->next) == 0) + if (pushfile(nm, fn, i, w->next) == 0) return 1; stringbuf = nm; } @@ -535,9 +403,9 @@ void include() { struct symtab *nl; - uchar *osp; - uchar *fn, *safefn; - int c; + usch *osp; + usch *fn, *safefn; + int c/*, it*/; if (flslvl) return; @@ -547,9 +415,12 @@ include() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -561,25 +432,26 @@ include() while ((c = sloscan()) != '>' && c != '\n') { if (c == '\n') /* XXX check - cannot reach */ goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); while ((c = sloscan()) == WSPACE) ; if (c != '\n') goto bad; + //it = SYSINC; safefn = fn; } else { - uchar *nm = stringbuf; + usch *nm = stringbuf; - yytext[strlen(yytext)-1] = 0; - fn = (uchar *)&yytext[1]; + yytext[strlen((char *)yytext)-1] = 0; + fn = (usch *)&yytext[1]; /* first try to open file relative to previous file */ /* but only if it is not an absolute path */ if (*fn != '/') { savstr(ifiles->orgfn); - stringbuf = (uchar *)strrchr((char *)nm, '/'); - if (stringbuf == NULL) + if ((stringbuf = + (usch *)strrchr((char *)nm, '/')) == NULL) stringbuf = nm; else stringbuf++; @@ -594,7 +466,7 @@ include() /* XXX may loose stringbuf space */ } - if (fsrch(safefn, INCINC, incdir[INCINC])) + if (fsrch(safefn, 0, incdir[0])) goto okret; error("cannot find '%s'", safefn); @@ -610,8 +482,8 @@ void include_next() { struct symtab *nl; - uchar *osp; - uchar *fn; + usch *osp; + usch *fn; int c; if (flslvl) @@ -621,9 +493,12 @@ include_next() ; if (c == IDENT) { /* sloscan() will not expand idents */ - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) + if ((nl = lookup((usch *)yytext, FIND)) == NULL) goto bad; - unpstr(gotident(nl)); + if (kfind(nl)) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = osp; c = yylex(); } @@ -632,13 +507,13 @@ include_next() fn = stringbuf; if (c == STRING) { - savstr((uchar *)&yytext[1]); + savstr((usch *)&yytext[1]); stringbuf[-1] = 0; } else { /* < > */ while ((c = sloscan()) != '>') { if (c == '\n') goto bad; - savstr((uchar *)yytext); + savstr((usch *)yytext); } savch('\0'); } @@ -672,14 +547,14 @@ getcmnt(void) { int c; - savstr((uchar *)yytext); + savstr((usch *)yytext); savch(cinput()); /* Lost * */ for (;;) { c = cinput(); if (c == '*') { c = cinput(); if (c == '/') { - savstr((const uchar *)"*/"); + savstr((const usch *)"*/"); return; } cunput(c); @@ -693,7 +568,7 @@ getcmnt(void) * Compare two replacement lists, taking in account comments etc. */ static int -cmprepl(const uchar *o, const uchar *n) +cmprepl(const usch *o, const usch *n) { for (; *o; o--, n--) { /* comment skip */ @@ -738,12 +613,12 @@ void define() { struct symtab *np; - uchar *args[MAXARG], *ubuf, *sbeg; + usch *args[MAXARGS+1], *ubuf, *sbeg; int c, i, redef; int mkstr = 0, narg = -1; int ellips = 0; -#ifdef GCC_VARI - uchar *gccvari = NULL; +#ifdef GCC_COMPAT + usch *gccvari = NULL; int wascon; #endif @@ -755,7 +630,7 @@ define() if (isdigit((int)yytext[0])) goto bad; - np = lookup((uchar *)yytext, ENTER); + np = lookup((usch *)yytext, ENTER); redef = np->value != NULL; readmac = 1; @@ -776,16 +651,18 @@ define() if (c == IDENT) { /* make sure there is no arg of same name */ for (i = 0; i < narg; i++) - if (!strcmp((char *) args[i], yytext)) + if (!strcmp((char *) args[i], (char *)yytext)) error("Duplicate macro " "parameter \"%s\"", yytext); + if (narg == MAXARGS) + error("Too many macro args"); args[narg++] = xstrdup(yytext); if ((c = definp()) == ',') { if ((c = definp()) == ')') goto bad; continue; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '.' && isell()) { if (definp() != ')') goto bad; @@ -813,7 +690,7 @@ define() if ((c = sloscan()) == '#') goto bad; savch('\0'); -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; #endif goto in2; @@ -822,7 +699,7 @@ define() /* parse replacement-list, substituting arguments */ savch('\0'); while (c != '\n') { -#ifdef GCC_VARI +#ifdef GCC_COMPAT wascon = 0; loop: #endif @@ -830,7 +707,7 @@ loop: case WSPACE: /* remove spaces if it surrounds a ## directive */ ubuf = stringbuf; - savstr((uchar *)yytext); + savstr((usch *)yytext); c = sloscan(); if (c == '#') { if ((c = sloscan()) != '#') @@ -839,7 +716,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -855,7 +732,7 @@ loop: savch(CONC); if ((c = sloscan()) == WSPACE) c = sloscan(); -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (c == '\n') break; wascon = 1; @@ -863,7 +740,7 @@ loop: #else continue; #endif - } + } in2: if (narg < 0) { /* no meaning in object-type macro */ savch('#'); @@ -874,15 +751,20 @@ in2: if (narg < 0) { if (c == WSPACE) c = sloscan(); /* whitespace, ignore */ mkstr = 1; - if (c == IDENT && strcmp(yytext, "__VA_ARGS__") == 0) + if (c == IDENT && strcmp((char *)yytext, "__VA_ARGS__") == 0) continue; /* FALLTHROUGH */ case IDENT: - if (strcmp(yytext, "__VA_ARGS__") == 0) { + if (strcmp((char *)yytext, "__VA_ARGS__") == 0) { if (ellips == 0) error("unwanted %s", yytext); +#ifdef GCC_COMPAT + savch(wascon ? GCCARG : VARG); +#else savch(VARG); +#endif + savch(WARN); if (mkstr) savch(SNUFF), mkstr = 0; @@ -892,12 +774,12 @@ in2: if (narg < 0) { goto id; /* just add it if object */ /* check if its an argument */ for (i = 0; i < narg; i++) - if (strcmp(yytext, (char *)args[i]) == 0) + if (strcmp((char *)yytext, (char *)args[i]) == 0) break; if (i == narg) { -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari && - strcmp(yytext, (char *)gccvari) == 0) { + strcmp((char *)yytext, (char *)gccvari) == 0) { savch(wascon ? GCCARG : VARG); savch(WARN); if (mkstr) @@ -920,7 +802,7 @@ in2: if (narg < 0) { break; default: -id: savstr((uchar *)yytext); +id: savstr((usch *)yytext); break; } c = sloscan(); @@ -936,7 +818,7 @@ id: savstr((uchar *)yytext); else break; } -#ifdef GCC_VARI +#ifdef GCC_COMPAT if (gccvari) { savch(narg); savch(VARG); @@ -947,17 +829,20 @@ id: savstr((uchar *)yytext); savch(VARG); } else savch(narg < 0 ? OBJCT : narg); - if (redef) { - if (cmprepl(np->value, stringbuf-1)) - error("%s redefined\nprevious define: %s:%d", + if (redef && ifiles->idx != SYSINC) { + if (cmprepl(np->value, stringbuf-1)) { + sbeg = stringbuf; + np->value = stringbuf-1; + warning("%s redefined\nprevious define: %s:%d", np->namep, np->file, np->line); + } stringbuf = sbeg; /* forget this space */ } else np->value = stringbuf-1; #ifdef CPP_DEBUG if (dflag) { - const uchar *w = np->value; + const usch *w = np->value; printf("!define: "); if (*w == OBJCT) @@ -983,44 +868,107 @@ bad: error("bad define"); } void -xwarning(uchar *s) +xwarning(usch *s) { - uchar *t; - uchar *sb = stringbuf; + usch *t; + usch *sb = stringbuf; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: warning: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); stringbuf = sb; } void -xerror(uchar *s) +xerror(usch *s) { - uchar *t; + usch *t; + //int dummy; flbuf(); savch(0); if (ifiles != NULL) { t = sheap("%s:%d: error: ", ifiles->fname, ifiles->lineno); - if (write (2, t, strlen((char *)t)) < 0) - /* ignore */; + /*dummy =*/ write (2, t, strlen((char *)t)); } - if (write (2, s, strlen((char *)s)) < 0) - /* ignore */; - if (write (2, "\n", 1) < 0) - /* ignore */; + /*dummy =*/ write (2, s, strlen((char *)s)); + /*dummy =*/ write (2, "\n", 1); exit(1); } +static void +sss(void) +{ + savch(EBLOCK); + savch(cinput()); + savch(cinput()); +} + +static int +addmac(struct symtab *sp) +{ + int c, i; + + /* Check if it exists; then save some space */ + /* May be more difficult to debug cpp */ + for (i = 1; i < norepptr; i++) + if (norep[i] == sp) + return i; + if (norepptr >= RECMAX) + error("too many macros"); + /* check norepptr */ + if ((norepptr & 255) == 0) + norepptr++; + if (((norepptr >> 8) & 255) == 0) + norepptr += 256; + c = norepptr; + norep[norepptr++] = sp; + return c; +} + +static void +doblk(void) +{ + int c; + + do { + donex(); + } while ((c = sloscan()) == EBLOCK); + if (c != IDENT) + error("EBLOCK sync error"); +} + +/* Block next nr in lex buffer to expand */ +int +donex(void) +{ + int n, i; + + if (bidx == RECMAX) + error("too deep macro recursion"); + n = cinput(); + n = MKB(n, cinput()); + for (i = 0; i < bidx; i++) + if (bptr[i] == n) + return n; /* already blocked */ + bptr[bidx++] = n; + /* XXX - check for sp buffer overflow */ + if (dflag>1) { + printf("donex %d (%d) blocking:\n", bidx, n); + printf("donex %s(%d) blocking:", norep[n]->namep, n); + for (i = bidx-1; i >= 0; i--) + printf(" '%s'", norep[bptr[i]]->namep); + printf("\n"); + } + return n; +} + /* * store a character into the "define" buffer. */ @@ -1028,240 +976,639 @@ void savch(int c) { if (stringbuf-sbf < SBSIZE) { - *stringbuf++ = (uchar)c; + *stringbuf++ = (usch)c; } else { stringbuf = sbf; /* need space to write error message */ error("Too much defining"); - } + } } /* - * substitute namep for sp->value. + * convert _Pragma to #pragma for output. + * Syntax is already correct. */ -int -subst(struct symtab *sp, struct recur *rp) +static void +pragoper(void) { - struct recur rp2; - register const uchar *vp, *cp; - register uchar *obp; - int c, nl; + usch *s; + int t; - DPRINT(("subst: %s\n", sp->namep)); - /* - * First check for special macros. - */ - if (sp == filloc) { - (void)sheap("\"%s\"", ifiles->fname); - return 1; - } else if (sp == linloc) { - (void)sheap("%d", ifiles->lineno); - return 1; + while ((t = sloscan()) != '(') + ; + + while ((t = sloscan()) == WSPACE) + ; + if (t != STRING) + error("pragma must have string argument"); + savstr((const usch *)"\n#pragma "); + s = (usch *)yytext; + if (*s == 'L') + s++; + for (; *s; s++) { + if (*s == '\"') + continue; + if (*s == '\\' && (s[1] == '\"' || s[1] == '\\')) + s++; + savch(*s); } - vp = sp->value; + sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname); + while ((t = sloscan()) == WSPACE) + ; + if (t != ')') + error("pragma syntax error"); +} - rp2.next = rp; - rp2.sp = sp; +/* + * Return true if it is OK to expand this symbol. + */ +static int +okexp(struct symtab *sp) +{ + int i; - if (*vp-- != OBJCT) { - int gotwarn = 0; - - /* should we be here at all? */ - /* check if identifier is followed by parentheses */ - - obp = stringbuf; - nl = 0; - do { - c = cinput(); - *stringbuf++ = (uchar)c; - if (c == WARN) { - gotwarn++; - if (rp == NULL) - break; - } - if (c == '\n') - nl++; - } while (c == ' ' || c == '\t' || c == '\n' || - c == '\r' || c == WARN); - - DPRINT(("c %d\n", c)); - if (c == '(' ) { - cunput(c); - stringbuf = obp; - ifiles->lineno += nl; - expdef(vp, &rp2, gotwarn); - return 1; - } else { - *stringbuf = 0; - unpstr(obp); - unpstr(sp->namep); - if ((c = sloscan()) != IDENT) - error("internal sync error"); - stringbuf = obp; + if (sp == NULL) + return 0; + for (i = 0; i < bidx; i++) + if (norep[bptr[i]] == sp) return 0; - } - } else { - cunput(WARN); - cp = vp; - while (*cp) { - if (*cp != CONC) - cunput(*cp); - cp--; - } - expmac(&rp2); - } return 1; } +/* + * Insert block(s) before each expanded name. + * Input is in lex buffer, output on lex buffer. + */ +static void +insblock(int bnr) +{ + usch *bp = stringbuf; + int c, i; + + IMP("IB"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + continue; + } + if (c == IDENT) { + savch(EBLOCK), savch(bnr & 255), savch(bnr >> 8); + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + } + savstr((const usch *)yytext); + if (c == '\n') + (void)cinput(); + } + savch(0); + cunput(WARN); + unpstr(bp); + stringbuf = bp; + IMP("IBRET"); +} + +/* Delete next WARN on the input stream */ +static void +delwarn(void) +{ + usch *bp = stringbuf; + int c; + + IMP("DELWARN"); + while ((c = sloscan()) != WARN) { + if (c == EBLOCK) { + sss(); + } else + savstr(yytext); + } + savch(0); + unpstr(bp); + stringbuf = bp; + IMP("DELWRET"); +} + +/* + * Handle defined macro keywords found on input stream. + * When finished print out the full expanded line. + * Everything on lex buffer except for the symtab. + */ +int +kfind(struct symtab *sp) +{ + struct symtab *nl; + const usch *argary[MAXARGS+1], *cbp; + usch *sbp; + int c, o, chkf; + + DPRINT(("%d:enter kfind(%s)\n",0,sp->namep)); + IMP("KFIND"); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + IMP("END1"); + cunput(WARN); + for (cbp = sp->value-1; *cbp; cbp--) + cunput(*cbp); + insblock(addmac(sp)); + IMP("ENDX"); + exparg(1); + +upp: sbp = stringbuf; + chkf = 1; + if (obufp != 0) + lastoch = outbuf[obufp-1]; + if (iswsnl(lastoch)) + chkf = 0; + while ((c = sloscan()) != WARN) { + switch (c) { + case STRING: + /* Remove embedded directives */ + for (cbp = (usch *)yytext; *cbp; cbp++) { + if (*cbp == EBLOCK) + cbp+=2; + else if (*cbp != CONC) + savch(*cbp); + } + break; + + case EBLOCK: + doblk(); + /* FALLTHROUGH */ + case IDENT: + /* + * Tricky: if this is the last identifier + * in the expanded list, and it is defined + * as a function-like macro, then push it + * back on the input stream and let fastscan + * handle it as a new macro. + * BUT: if this macro is blocked then this + * should not be done. + */ + nl = lookup((usch *)yytext, FIND); + o = okexp(nl); + bidx = 0; + /* Deal with pragmas here */ + if (nl == pragloc) { + pragoper(); + break; + } + if (nl == NULL || !o || *nl->value == OBJCT) { + /* Not fun-like macro */ + savstr(yytext); + break; + } + c = cinput(); + if (c == WARN) { + /* succeeded, push back */ + unpstr(yytext); + } else { + savstr(yytext); + } + cunput(c); + break; + + default: + if (chkf && c < 127) + putch(' '); + savstr(yytext); + break; + } + chkf = 0; + } + IMP("END2"); + norepptr = 1; + savch(0); + stringbuf = sbp; + return 1; + } + /* Is a function-like macro */ + + /* Search for '(' */ + sbp = stringbuf; + while (iswsnl(c = cinput())) + savch(c); + savch(0); + stringbuf = sbp; + if (c != '(') { + cunput(c); + unpstr(sbp); + return 0; /* Failed */ + } + + /* Found one, output \n to be in sync */ + for (; *sbp; sbp++) { + if (*sbp == '\n') + putch('\n'), ifiles->lineno++; + } + + /* fetch arguments */ + if (readargs(sp, argary)) + error("readargs"); + + c = addmac(sp); + sbp = stringbuf; + cunput(WARN); + + IMP("KEXP"); + subarg(sp, argary, 1); + IMP("KNEX"); + insblock(c); + IMP("KBLK"); + + stringbuf = sbp; + + exparg(1); + + IMP("END"); + + goto upp; + +} + +/* + * Replace and push-back on input stream the eventual replaced macro. + * The check for whether it can expand or not should already have been done. + * Blocks for this identifier will be added via insblock() after expansion. + */ +int +submac(struct symtab *sp, int lvl) +{ + const usch *argary[MAXARGS+1]; + const usch *cp; + usch *bp; + int ch; + + DPRINT(("%d:submac1: trying '%s'\n", lvl, sp->namep)); + if (*sp->value == OBJCT) { + if (sp == filloc) { + unpstr(sheap("\"%s\"", ifiles->fname)); + return 1; + } else if (sp == linloc) { + unpstr(sheap("%d", ifiles->lineno)); + return 1; + } + + DPRINT(("submac: exp object macro '%s'\n",sp->namep)); + /* expand object-type macros */ + ch = addmac(sp); + cunput(WARN); + + for (cp = sp->value-1; *cp; cp--) + cunput(*cp); + insblock(ch); + delwarn(); + return 1; + } + + /* + * Function-like macro; see if it is followed by a ( + * Be careful about the expand/noexpand balance. + * Store read data on heap meanwhile. + * For directive #define foo() kaka + * If input is foo() then + * output should be kaka. + */ + bp = stringbuf; + while (iswsnl(ch = cinput())) + savch(ch); + savch(0); + stringbuf = bp; + if (ch != '(') { + cunput(ch); + unpstr(bp); + return 0; /* Failed */ + } + + /* no \n should be here */ + + /* + * A function-like macro has been found. Read in the arguments, + * expand them and push-back everything for another scan. + */ + DPRINT(("%d:submac: continue macro '%s'\n", lvl, sp->namep)); + savch(0); + if (readargs(sp, argary)) { + /* Bailed out in the middle of arg list */ + unpstr(bp); + if (dflag>1)printf("%d:noreadargs\n", lvl); + stringbuf = bp; + return 0; + } + + /* when all args are read from input stream */ + ch = addmac(sp); + + DDPRINT(("%d:submac pre\n", lvl)); + cunput(WARN); + + subarg(sp, argary, lvl+1); + + DDPRINT(("%d:submac post\n", lvl)); + insblock(ch); + delwarn(); + + stringbuf = bp; /* Reset heap */ + DPRINT(("%d:Return submac\n", lvl)); + IMP("SM1"); + return 1; +} + +/* + * Read arguments and put in argument array. + * If WARN is encountered return 1, otherwise 0. + */ +int +readargs(struct symtab *sp, const usch **args) +{ + const usch *vp = sp->value; + int c, i, plev, narg, ellips = 0; + int warn; + + DPRINT(("readargs\n")); + + narg = *vp--; + if (narg == VARG) { + narg = *vp--; + ellips = 1; + } + + IMP("RDA1"); + /* + * read arguments and store them on heap. + */ + warn = 0; + c = '('; + for (i = 0; i < narg && c != ')'; i++) { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + putch(cinput()); + for (;;) { + while (c == EBLOCK) { + sss(); + c = sloscan(); + } + if (c == WARN) { + warn++; + goto oho; + } + if (plev == 0 && (c == ')' || c == ',')) + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + savstr((usch *)yytext); +oho: while ((c = sloscan()) == '\n') { + putch(cinput()); + savch(' '); + } + while (c == CMNT) { + getcmnt(); + c = sloscan(); + } + if (c == 0) + error("eof in macro"); + } + while (args[i] < stringbuf && + iswsnl(stringbuf[-1]) && stringbuf[-3] != EBLOCK) + stringbuf--; + savch('\0'); + if (dflag) { + printf("readargs: save arg %d '", i); + prline(args[i]); + printf("'\n"); + } + } + + IMP("RDA2"); + /* Handle varargs readin */ + if (ellips) + args[i] = (const usch *)""; + if (ellips && c != ')') { + args[i] = stringbuf; + plev = 0; + while ((c = sloscan()) == WSPACE) + ; + for (;;) { + if (plev == 0 && c == ')') + break; + if (c == '(') + plev++; + if (c == ')') + plev--; + if (c == EBLOCK) { + sss(); + } else + savstr((usch *)yytext); + while ((c = sloscan()) == '\n') { + cinput(); + savch(' '); + } + } + while (args[i] < stringbuf && iswsnl(stringbuf[-1])) + stringbuf--; + savch('\0'); + + } + if (narg == 0 && ellips == 0) + while ((c = sloscan()) == WSPACE || c == '\n') + if (c == '\n') + cinput(); + + if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) + error("wrong arg count"); + while (warn) + cunput(WARN), warn--; + return 0; +} + +#if 0 /* * Maybe an indentifier (for macro expansion). */ static int -mayid(uchar *s) +mayid(usch *s) { for (; *s; s++) if (!isdigit(*s) && !isalpha(*s) && *s != '_') return 0; return 1; } +#endif /* - * do macro-expansion until WARN character read. - * read from lex buffer and store result on heap. - * will recurse into lookup() for recursive expansion. - * when returning all expansions on the token list is done. + * expand a function-like macro. + * vp points to end of replacement-list + * reads function arguments from sloscan() + * result is pushed-back for more scanning. */ void -expmac(struct recur *rp) +subarg(struct symtab *nl, const usch **args, int lvl) +{ + int narg, instr, snuff; + const usch *sp, *bp, *ap, *vp; + + DPRINT(("%d:subarg '%s'\n", lvl, nl->namep)); + vp = nl->value; + narg = *vp--; + if (narg == VARG) + narg = *vp--; + + sp = vp; + instr = snuff = 0; + if (dflag>1) { + printf("%d:subarg ARGlist for %s: '", lvl, nl->namep); + prrep(vp); + printf("'\n"); + } + + /* + * push-back replacement-list onto lex buffer while replacing + * arguments. Arguments are macro-expanded if required. + */ + while (*sp != 0) { + if (*sp == SNUFF) + cunput('\"'), snuff ^= 1; + else if (*sp == CONC) + ; + else if (*sp == WARN) { + + if (sp[-1] == VARG) { + bp = ap = args[narg]; + sp--; +#ifdef GCC_COMPAT + } else if (sp[-1] == GCCARG) { + ap = args[narg]; + if (ap[0] == 0) + ap = (const usch *)"0"; + bp = ap; + sp--; +#endif + } else + bp = ap = args[(int)*--sp]; + if (dflag>1){ + printf("%d:subarg GOTwarn; arglist '", lvl); + prline(bp); + printf("'\n"); + } + if (sp[2] != CONC && !snuff && sp[-1] != CONC) { + /* + * Expand an argument; 6.10.3.1: + * "A parameter in the replacement list, + * is replaced by the corresponding argument + * after all macros contained therein have + * been expanded.". + */ + cunput(WARN); + unpstr(bp); + exparg(lvl+1); + delwarn(); + } else { + while (*bp) + bp++; + while (bp > ap) { + bp--; + if (snuff && !instr && iswsnl(*bp)) { + while (iswsnl(*bp)) + bp--; + cunput(' '); + } + + cunput(*bp); + if ((*bp == '\'' || *bp == '"') + && bp[-1] != '\\' && snuff) { + instr ^= 1; + if (instr == 0 && *bp == '"') + cunput('\\'); + } + if (instr && (*bp == '\\' || *bp == '"')) + cunput('\\'); + } + } + } else + cunput(*sp); + sp--; + } + DPRINT(("%d:Return subarg\n", lvl)); + IMP("SUBARG"); +} + +/* + * Do a (correct) expansion of a WARN-terminated buffer of tokens. + * Data is read from the lex buffer, result on lex buffer, WARN-terminated. + * Expansion blocking is not altered here unless when tokens are + * concatenated, in which case they are removed. + */ +void +exparg(int lvl) { struct symtab *nl; - int c, noexp = 0, orgexp; - uchar *och, *stksv; + int c, i; + usch *och; + usch *osb = stringbuf; + int anychange; + + DPRINT(("%d:exparg\n", lvl)); + IMP("EXPARG"); -#ifdef CPP_DEBUG - if (dflag) { - struct recur *rp2 = rp; - printf("\nexpmac\n"); - while (rp2) { - printf("do not expand %s\n", rp2->sp->namep); - rp2 = rp2->next; - } - } -#endif readmac++; +rescan: + anychange = 0; while ((c = sloscan()) != WARN) { + DDPRINT(("%d:exparg swdata %d\n", lvl, c)); + IMP("EA0"); switch (c) { - case NOEXP: noexp++; break; - case EXPAND: noexp--; break; - case NUMBER: /* handled as ident if no .+- in it */ - if (!mayid((uchar *)yytext)) - goto def; + case EBLOCK: + doblk(); /* FALLTHROUGH */ case IDENT: /* * Handle argument concatenation here. - * If an identifier is found and directly - * after EXPAND or NOEXP then push the - * identifier back on the input stream and - * call sloscan() again. - * Be careful to keep the noexp balance. + * In case of concatenation, scratch all blockings. */ + DDPRINT(("%d:exparg ident %d\n", lvl, c)); och = stringbuf; - savstr((uchar *)yytext); - DDPRINT(("id: str %s\n", och)); - orgexp = 0; - while ((c = sloscan()) == EXPAND || c == NOEXP) - if (c == EXPAND) - orgexp--; - else - orgexp++; +sav: savstr(yytext); - DDPRINT(("id1: typ %d noexp %d orgexp %d\n", - c, noexp, orgexp)); - if (c == IDENT || - (c == NUMBER && mayid((uchar *)yytext))) { - DDPRINT(("id2: str %s\n", yytext)); - /* OK to always expand here? */ - savstr((uchar *)yytext); - switch (orgexp) { - case 0: /* been EXP+NOEXP */ - if (noexp == 0) - break; - if (noexp != 1) - error("case 0"); - cunput(NOEXP); - noexp = 0; - break; - case -1: /* been EXP */ - if (noexp != 1) - error("case -1"); - noexp = 0; - break; - case 1: - if (noexp != 0) - error("case 1"); - cunput(NOEXP); - break; - default: - error("orgexp = %d", orgexp); + if ((c = cinput()) == EBLOCK) { + /* yep, are concatenating; forget blocks */ + do { + (void)cinput(); + (void)cinput(); + } while ((c = sloscan()) == EBLOCK); + bidx = 0; + goto sav; + } + cunput(c); + + DPRINT(("%d:exparg: str '%s'\n", lvl, och)); + IMP("EA1"); + /* see if ident is expandable */ + if ((nl = lookup(och, FIND)) && okexp(nl)) { + if (submac(nl, lvl+1)) { + /* Could expand, result on lexbuffer */ + stringbuf = och; /* clear saved name */ + anychange = 1; } - unpstr(och); + } else if (bidx) { + /* must restore blocks */ stringbuf = och; - continue; /* New longer identifier */ + for (i = 0; i < bidx; i++) + savch(EBLOCK), savch(bptr[i] & 255), + savch(bptr[i] >> 8); + savstr(yytext); } - unpstr((const uchar *)yytext); - if (orgexp == -1) - cunput(EXPAND); - else if (orgexp == -2) - cunput(EXPAND), cunput(EXPAND); - else if (orgexp == 1) - cunput(NOEXP); - unpstr(och); - stringbuf = och; - - - sloscan(); /* XXX reget last identifier */ - - if ((nl = lookup((uchar *)yytext, FIND)) == NULL) - goto def; - - if (canexpand(rp, nl) == 0) - goto def; - /* - * If noexp == 0 then expansion of any macro is - * allowed. If noexp == 1 then expansion of a - * fun-like macro is allowed iff there is an - * EXPAND between the identifier and the '('. - */ - if (noexp == 0) { - if ((c = subst(nl, rp)) == 0) - goto def; - break; - } - if (noexp != 1) - error("bad noexp %d", noexp); - stksv = NULL; - if ((c = sloscan()) == WSPACE) { - stksv = xstrdup(yytext); - c = sloscan(); - } - /* only valid for expansion if fun macro */ - if (c == EXPAND && *nl->value != OBJCT) { - noexp--; - if (subst(nl, rp)) - break; - savstr(nl->namep); - if (stksv) - savstr(stksv); - } else { - unpstr((const uchar *)yytext); - if (stksv) - unpstr(stksv); - savstr(nl->namep); - } - if (stksv) - free(stksv); + bidx = 0; + IMP("EA2"); break; case CMNT: @@ -1273,237 +1620,65 @@ expmac(struct recur *rp) savch(' '); break; - case STRING: - /* remove EXPAND/NOEXP from strings */ - if (yytext[1] == NOEXP) { - savch('"'); - och = (uchar *)&yytext[2]; - while (*och != EXPAND) - savch(*och++); - savch('"'); - break; - } - /* FALLTHROUGH */ - -def: default: - savstr((uchar *)yytext); + default: + savstr((usch *)yytext); break; } } - if (noexp) - error("expmac noexp=%d", noexp); - readmac--; - DPRINT(("return from expmac\n")); -} - -/* - * expand a function-like macro. - * vp points to end of replacement-list - * reads function arguments from sloscan() - * result is written on top of heap - */ -void -expdef(const uchar *vp, struct recur *rp, int gotwarn) -{ - const uchar **args, *ap, *bp, *sp; - uchar *sptr; - int narg, c, i, plev, snuff, instr; - int ellips = 0, shot = gotwarn; - size_t allocsz; - - DPRINT(("expdef rp %s\n", (rp ? (const char *)rp->sp->namep : ""))); - c = sloscan(); - if (c != '(') - error("got %c, expected (", c); - - if (vp[1] == VARG) { - narg = *vp--; - ellips = 1; - } else - narg = vp[1]; - - // The code depends on malloc(0) returning a non-NULL pointer, which is not guaranteed. - // Workaround it. - allocsz = sizeof(uchar *) * ((narg+ellips) ? (narg+ellips) : 1); - args = malloc(allocsz); - if (args == NULL) - error("expdef: out of mem"); - - /* - * read arguments and store them on heap. - * will be removed just before return from this function. - */ - sptr = stringbuf; - instr = 0; - for (i = 0; i < narg && c != ')'; i++) { - args[i] = stringbuf; - plev = 0; - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - putch(cinput()); - DDPRINT((":AAA (%d)", c)); - if (instr == -1) - savch(NOEXP), instr = 1; - if (c == NOEXP) - instr = 1; - for (;;) { - if (plev == 0 && (c == ')' || c == ',')) - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - putch(cinput()); - savch('\n'); - } - while (c == CMNT) { - getcmnt(); - c = sloscan(); - } - if (c == EXPAND) - instr = 0; - if (c == 0) - error("eof in macro"); - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - if (instr == 1) - savch(EXPAND), instr = -1; - savch('\0'); - } - if (ellips) - args[i] = (const uchar *)""; - if (ellips && c != ')') { - args[i] = stringbuf; - plev = 0; - instr = 0; - while ((c = sloscan()) == WSPACE) - ; - if (c == NOEXP) - instr++; - DDPRINT((":AAY (%d)", c)); - for (;;) { - if (plev == 0 && c == ')') - break; - if (c == '(') - plev++; - if (c == ')') - plev--; - if (plev == 0 && c == ',' && instr) { - savch(EXPAND); - savch(','); - savch(NOEXP); - } else - savstr((uchar *)yytext); - while ((c = sloscan()) == '\n') { - cinput(); - savch('\n'); - } - if (c == EXPAND) - instr--; - } - while (args[i] < stringbuf && - (stringbuf[-1] == ' ' || stringbuf[-1] == '\t')) - stringbuf--; - savch('\0'); - - } - if (narg == 0 && ellips == 0) - while ((c = sloscan()) == WSPACE || c == '\n') - if (c == '\n') - cinput(); - - if (c != ')' || (i != narg && ellips == 0) || (i < narg && ellips == 1)) - error("wrong arg count"); - - while (gotwarn--) - cunput(WARN); - - sp = vp; - instr = snuff = 0; - - /* - * push-back replacement-list onto lex buffer while replacing - * arguments. - */ + *stringbuf = 0; cunput(WARN); - while (*sp != 0) { - if (*sp == SNUFF) - cunput('\"'), snuff ^= 1; - else if (*sp == CONC) - ; - else if (*sp == WARN) { - - if (sp[-1] == VARG) { - bp = ap = args[narg]; - sp--; -#ifdef GCC_VARI - } else if (sp[-1] == GCCARG) { - ap = args[narg]; - if (ap[0] == 0) - ap = (const uchar *)"0"; - bp = ap; - sp--; -#endif - } else - bp = ap = args[(int)*--sp]; - if (sp[2] != CONC && !snuff && sp[-1] != CONC) { - struct recur *r2 = rp->next; - cunput(WARN); - while (*bp) - bp++; - while (bp > ap) - cunput(*--bp); - DPRINT(("expand arg %d string %s\n", *sp, ap)); - bp = ap = stringbuf; - savch(NOEXP); - while (shot && r2) - r2 = r2->next, shot--; - expmac(r2); - savch(EXPAND); - savch('\0'); - } - while (*bp) - bp++; - while (bp > ap) { - bp--; - if (snuff && !instr && - (*bp == ' ' || *bp == '\t' || *bp == '\n')){ - while (*bp == ' ' || *bp == '\t' || - *bp == '\n') { - bp--; - } - cunput(' '); - } - if (!snuff || (*bp != EXPAND && *bp != NOEXP)) - cunput(*bp); - if ((*bp == '\'' || *bp == '"') - && bp[-1] != '\\' && snuff) { - instr ^= 1; - if (instr == 0 && *bp == '"') - cunput('\\'); - } - if (instr && (*bp == '\\' || *bp == '"')) - cunput('\\'); - } - } else - cunput(*sp); - sp--; - } - stringbuf = sptr; - - /* scan the input buffer (until WARN) and save result on heap */ - expmac(rp); - free(args); + unpstr(osb); + DPRINT(("%d:exparg return: change %d\n", lvl, anychange)); + IMP("EXPRET"); + stringbuf = osb; + if (anychange) + goto rescan; + readmac--; } -uchar * -savstr(const uchar *str) +void +imp(const char *str) { - uchar *rv = stringbuf; + printf("%s (%d) '", str, bidx); + prline(ifiles->curptr); + printf("'\n"); +} + +void +prrep(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf("", *--s); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[-1] + s[-2] * 256); s-=2; break; + default: printf("%c", *s); break; + } + s--; + } +} + +void +prline(const usch *s) +{ + while (*s) { + switch (*s) { + case WARN: printf(""); break; + case CONC: printf(""); break; + case SNUFF: printf(""); break; + case EBLOCK: printf("",s[1] + s[2] * 256); s+=2; break; + case '\n': printf(""); break; + default: printf("%c", *s); break; + } + s++; + } +} + +usch * +savstr(const usch *str) +{ + usch *rv = stringbuf; do { if (stringbuf >= &sbf[SBSIZE]) { @@ -1515,25 +1690,23 @@ savstr(const uchar *str) return rv; } -int -canexpand(struct recur *rp, struct symtab *np) -{ - struct recur *w; - - for (w = rp; w && w->sp != np; w = w->next) - ; - if (w != NULL) - return 0; - return 1; -} - void -unpstr(const uchar *c) +unpstr(const usch *c) { - const uchar *d = c; + const usch *d = c; - while (*d) +#if 0 + if (dflag>1) { + printf("Xunpstr: '"); + prline(c); + printf("'\n"); + } +#endif + while (*d) { + if (*d == EBLOCK) + d += 2; d++; + } while (d > c) { cunput(*--d); } @@ -1546,19 +1719,20 @@ flbuf() return; if (Mflag == 0 && write(ofd, outbuf, obufp) < 0) error("obuf write error"); + lastoch = outbuf[obufp-1]; obufp = 0; } void putch(int ch) { - outbuf[obufp++] = (uchar)ch; + outbuf[obufp++] = (usch)ch; if (obufp == CPPBUF || (istty && ch == '\n')) flbuf(); } void -putstr(const uchar *s) +putstr(const usch *s) { for (; *s; s++) { outbuf[obufp++] = *s; @@ -1573,14 +1747,14 @@ putstr(const uchar *s) static void num2str(int num) { - static uchar buf[12]; - uchar *b = buf; + static usch buf[12]; + usch *b = buf; int m = 0; - + if (num < 0) num = -num, m = 1; do { - *b++ = (uchar)(num % 10 + '0'); + *b++ = (usch)(num % 10 + '0'); num /= 10; } while (num); if (m) @@ -1590,14 +1764,14 @@ num2str(int num) } /* - * similar to sprintf, but only handles %s and %d. + * similar to sprintf, but only handles %s and %d. * saves result on heap. */ -uchar * +usch * sheap(const char *fmt, ...) { va_list ap; - uchar *op = stringbuf; + usch *op = stringbuf; va_start(ap, fmt); for (; *fmt; fmt++) { @@ -1605,7 +1779,7 @@ sheap(const char *fmt, ...) fmt++; switch (*fmt) { case 's': - savstr(va_arg(ap, uchar *)); + savstr(va_arg(ap, usch *)); break; case 'd': num2str(va_arg(ap, int)); @@ -1630,13 +1804,26 @@ usage() error("Usage: cpp [-Cdt] [-Dvar=val] [-Uvar] [-Ipath] [-Spath]"); } +#ifdef notyet /* * Symbol table stuff. - * The data structure used is a patricia tree implementation. + * The data structure used is a patricia tree implementation using only + * bytes to store offsets. + * The information stored is (lower address to higher): + * + * unsigned char bitno[2]; bit number in the string + * unsigned char left[3]; offset from base to left element + * unsigned char right[3]; offset from base to right element + */ +#endif + +/* + * This patricia implementation is more-or-less the same as + * used in ccom for string matching. */ struct tree { - int bitno; /* bit number in the string */ - struct tree *lr[2]; /* left/right element */ + int bitno; + struct tree *lr[2]; }; #define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF)) @@ -1654,7 +1841,7 @@ static int numsyms; * Allocate a symtab struct and store the string. */ static struct symtab * -getsymtab(const uchar *str) +getsymtab(const usch *str) { struct symtab *sp = malloc(sizeof(struct symtab)); @@ -1663,7 +1850,7 @@ getsymtab(const uchar *str) sp->namep = savstr(str); savch('\0'); sp->value = NULL; - sp->file = ifiles ? ifiles->orgfn : (const uchar *)""; + sp->file = ifiles ? ifiles->orgfn : (const usch *)""; sp->line = ifiles ? ifiles->lineno : 0; return sp; } @@ -1673,12 +1860,12 @@ getsymtab(const uchar *str) * Only do full string matching, no pointer optimisations. */ struct symtab * -lookup(const uchar *key, int enterf) +lookup(const usch *key, int enterf) { struct symtab *sp; struct tree *w, *new, *last; int len, cix, bit, fbit, svbit, ix, bitno; - const uchar *k, *m; + const usch *k, *m/*, *sm*/; /* Count full string length */ for (k = key, len = 0; *k; k++, len++) @@ -1694,6 +1881,7 @@ lookup(const uchar *key, int enterf) case 1: w = sympole; + svbit = 0; /* XXX gcc */ break; default: @@ -1712,7 +1900,7 @@ lookup(const uchar *key, int enterf) sp = (struct symtab *)w; - m = sp->namep; + /*sm =*/ m = sp->namep; k = key; /* Check for correct string and return */ @@ -1732,8 +1920,7 @@ lookup(const uchar *key, int enterf) ix >>= 1, cix++; /* Create new node */ - new = malloc(sizeof *new); - if (! new) + if ((new = malloc(sizeof *new)) == NULL) error("getree: couldn't allocate tree"); bit = P_BIT(key, cix); new->bitno = cix | (bit ? RIGHT_IS_LEAF : LEFT_IS_LEAF); @@ -1748,7 +1935,6 @@ lookup(const uchar *key, int enterf) w = sympole; last = NULL; - svbit = 0; /* XXX gcc */ for (;;) { fbit = w->bitno; bitno = BITNO(w->bitno); @@ -1774,3 +1960,15 @@ lookup(const uchar *key, int enterf) new->bitno |= (bit ? LEFT_IS_LEAF : RIGHT_IS_LEAF); return (struct symtab *)new->lr[bit]; } + +usch * +xstrdup(const usch *str) +{ + size_t len = strlen((const char *)str)+1; + usch *rv; + + if ((rv = malloc(len)) == NULL) + error("xstrdup: out of mem"); + strlcpy((char *)rv, (const char *)str, len); + return rv; +} diff --git a/src/cmd/cpp/cpp.h b/src/cmd/cpp/cpp.h index 1356dd8..bebc226 100644 --- a/src/cmd/cpp/cpp.h +++ b/src/cmd/cpp/cpp.h @@ -1,5 +1,7 @@ +/* $Id: cpp.h,v 1.47.2.1 2011/02/26 06:36:40 ragge Exp $ */ + /* - * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). + * Copyright (c) 2004,2010 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,8 +12,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -24,25 +24,15 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef CROSS -# include -# include -#else -# include /* for obuf */ -# include -#endif + +#include /* for obuf */ #include -/* Version string */ -#define VERSSTR "cpp for RetroBSD" +#include "config.h" -typedef unsigned char uchar; -#ifdef YYTEXT_POINTER -extern char *yytext; -#else -extern char yytext[]; -#endif -extern uchar *stringbuf; +typedef unsigned char usch; +extern usch yytext[]; +extern usch *stringbuf; extern int trulvl; extern int flslvl; @@ -50,7 +40,7 @@ extern int elflvl; extern int elslvl; extern int tflag, Cflag, Pflag; extern int Mflag, dMflag; -extern uchar *Mfile; +extern usch *Mfile; extern int ofd; /* args for lookup() */ @@ -58,32 +48,77 @@ extern int ofd; #define ENTER 1 /* buffer used internally */ -#define CPPBUF 512 +#define CPPBUF 512 +#ifndef CPPBUF +#if defined(__pdp11__) +#define CPPBUF BUFSIZ +#define BUF_STACK +#elif defined(WIN32) +/* winxp seems to fail > 26608 bytes */ +#define CPPBUF 16384 +#else +#define CPPBUF (65536*2) +#endif +#endif + +#define MAXARGS 20//128 /* Max # of args to a macro. Should be enouth */ #define NAMEMAX CPPBUF /* currently pushbackbuffer */ +#define BBUFSZ (NAMEMAX+CPPBUF+1) + +#define GCCARG 0xfd /* has gcc varargs that may be replaced with 0 */ +#define VARG 0xfe /* has varargs */ +#define OBJCT 0xff +#define WARN 1 /* SOH, not legal char */ +#define CONC 2 /* STX, not legal char */ +#define SNUFF 3 /* ETX, not legal char */ +#define EBLOCK 4 /* EOT, not legal char */ + +/* Used in macro expansion */ +#define RECMAX 400//10000 /* max # of recursive macros */ +extern struct symtab *norep[RECMAX]; +extern int norepptr; +extern unsigned short bptr[RECMAX]; +extern int bidx; +#define MKB(l,h) (l+((h)<<8)) + +/* quick checks for some characters */ +#define C_SPEC 001 +#define C_EP 002 +#define C_ID 004 +#define C_I (C_SPEC|C_ID) +#define C_2 010 /* for yylex() tokenizing */ +#define C_WSNL 020 /* ' ','\t','\r','\n' */ +#define iswsnl(x) (spechr[x] & C_WSNL) +extern char spechr[]; /* definition for include file info */ struct includ { struct includ *next; - const uchar *fname; /* current fn, changed if #line found */ - const uchar *orgfn; /* current fn, not changed */ + const usch *fname; /* current fn, changed if #line found */ + const usch *orgfn; /* current fn, not changed */ int lineno; int infil; - uchar *curptr; - uchar *maxread; - uchar *ostr; - uchar *buffer; + usch *curptr; + usch *maxread; + usch *ostr; + usch *buffer; int idx; void *incs; - const uchar *fn; - uchar bbuf[NAMEMAX+CPPBUF+1]; -} *ifiles; + const usch *fn; +#ifdef BUF_STACK + usch bbuf[BBUFSZ]; +#else + usch *bbuf; +#endif +}; +extern struct includ *ifiles; /* Symbol table entry */ struct symtab { - const uchar *namep; - const uchar *value; - const uchar *file; + const usch *namep; + const usch *value; + const usch *file; int line; }; @@ -110,13 +145,15 @@ struct nd { #define nd_val n.val #define nd_uval n.uval -struct recur; /* not used outside cpp.c */ -int subst(struct symtab *, struct recur *); -struct symtab *lookup(const uchar *namep, int enterf); -uchar *gotident(struct symtab *nl); -int slow; /* scan slowly for new tokens */ +struct symtab *lookup(const usch *namep, int enterf); +usch *gotident(struct symtab *nl); +extern int slow; /* scan slowly for new tokens */ +int submac(struct symtab *nl, int); +int kfind(struct symtab *nl); +int doexp(void); +int donex(void); -int pushfile(const uchar *fname, const uchar *fn, int idx, void *incs); +int pushfile(const usch *fname, const usch *fn, int idx, void *incs); void popfile(void); void prtline(void); int yylex(void); @@ -128,18 +165,22 @@ void setline(int); void setfile(char *); int yyparse(void); void yyerror(const char *); -void unpstr(const uchar *); -uchar *savstr(const uchar *str); +void unpstr(const usch *); +usch *savstr(const usch *str); void savch(int c); void mainscan(void); void putch(int); -void putstr(const uchar *s); +void putstr(const usch *s); void line(void); -uchar *sheap(const char *fmt, ...); -void xwarning(uchar *); -void xerror(uchar *); -#define warning(args...) xwarning(sheap(args)) -#define error(args...) xerror(sheap(args)) -void expmac(struct recur *); +usch *sheap(const char *fmt, ...); +void xwarning(usch *); +void xerror(usch *); +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define warning(...) xwarning(sheap(__VA_ARGS__)) +#define error(...) xerror(sheap(__VA_ARGS__)) +#else +#define warning printf +#define error printf +#endif int cinput(void); void getcmnt(void); diff --git a/src/cmd/cpp/cpy.y b/src/cmd/cpp/cpy.y index 4e4c1a5..78bc3ca 100644 --- a/src/cmd/cpp/cpy.y +++ b/src/cmd/cpp/cpy.y @@ -1,3 +1,5 @@ +/* $Id: cpy.y,v 1.18 2010/02/25 15:49:00 ragge Exp $ */ + /* * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se). * All rights reserved. @@ -58,6 +60,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + %{ #include "cpp.h" diff --git a/src/cmd/cpp/scanner.l b/src/cmd/cpp/scanner.l new file mode 100644 index 0000000..f1e4bf9 --- /dev/null +++ b/src/cmd/cpp/scanner.l @@ -0,0 +1,939 @@ +%{ +/* $Id: scanner.l,v 1.49 2009/02/14 09:23:55 ragge Exp $ */ + +/* + * Copyright (c) 2004 Anders Magnusson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "compat.h" +#include "cpp.h" +#include "y.tab.h" +%} + +%{ +static void cvtdig(int rad); +static int charcon(usch *); +static void elsestmt(void); +static void ifdefstmt(void); +static void ifndefstmt(void); +static void endifstmt(void); +static void ifstmt(void); +static void cpperror(void); +static void pragmastmt(void); +static void undefstmt(void); +static void cpperror(void); +static void elifstmt(void); +static void storepb(void); +static void badop(const char *); +void include(void); +void define(void); + +extern int yyget_lineno (void); +extern void yyset_lineno (int); + +static int inch(void); + +static int scale, gotdef, contr; +int inif; + +#ifdef FLEX_SCANNER /* should be set by autoconf instead */ +static int +yyinput(char *b, int m) +{ + int c, i; + + for (i = 0; i < m; i++) { + if ((c = inch()) < 0) + break; + *b++ = c; + if (c == '\n') { + i++; + break; + } + } + return i; +} +#undef YY_INPUT +#undef YY_BUF_SIZE +#define YY_BUF_SIZE (8*65536) +#define YY_INPUT(b,r,m) (r = yyinput(b, m)) +#ifdef HAVE_CPP_VARARG_MACRO_GCC +#define fprintf(x, ...) error(__VA_ARGS__) +#endif +#define ECHO putstr((usch *)yytext) +#undef fileno +#define fileno(x) 0 + +#if YY_FLEX_SUBMINOR_VERSION >= 31 +/* Hack to avoid unnecessary warnings */ +FILE *yyget_in (void); +FILE *yyget_out (void); +int yyget_leng (void); +char *yyget_text (void); +void yyset_in (FILE * in_str ); +void yyset_out (FILE * out_str ); +int yyget_debug (void); +void yyset_debug (int bdebug ); +int yylex_destroy (void); +#endif +#else /* Assume lex here */ +#undef input +#undef unput +#define input() inch() +#define unput(ch) unch(ch) +#endif +#define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext); +/* protection against recursion in #include */ +#define MAX_INCLEVEL 100 +static int inclevel; +%} + +D [0-9] +L [a-zA-Z_] +H [a-fA-F0-9] +E [Ee][+-]?{D}+ +FS (f|F|l|L) +IS (u|U|l|L)* +WS [\t ] + +%s IFR CONTR DEF COMMENT + +%% + +"\n" { int os = YYSTATE; + if (os != IFR) + BEGIN 0; + ifiles->lineno++; + if (flslvl == 0) { + if (ifiles->lineno == 1) + prtline(); + else + putch('\n'); + } + if ((os != 0 || slow) && !contr) + return '\n'; + contr = 0; + } + +"\r" { ; /* Ignore CR's */ } + +"++" { badop("++"); } +"--" { badop("--"); } +"==" { return EQ; } +"!=" { return NE; } +"<=" { return LE; } +"<<" { return LS; } +">>" { return RS; } +">=" { return GE; } +"||" { return OROR; } +"&&" { return ANDAND; } +"defined" { int p, c; + gotdef = 1; + if ((p = c = yylex()) == '(') + c = yylex(); + if (c != IDENT || (p != IDENT && p != '(')) + error("syntax error"); + if (p == '(' && yylex() != ')') + error("syntax error"); + return NUMBER; + } + +{WS}+ { ; } +{L}({L}|{D})* { + yylval.node.op = NUMBER; + if (gotdef) { + yylval.node.nd_val + = lookup((usch *)yytext, FIND) != 0; + gotdef = 0; + return IDENT; + } + yylval.node.nd_val = 0; + return NUMBER; + } + +[0-9][0-9]* { + if (slow && !YYSTATE) + return IDENT; + scale = yytext[0] == '0' ? 8 : 10; + goto num; + } + +0[xX]{H}+{IS}? { scale = 16; + num: if (YYSTATE == IFR) + cvtdig(scale); + PRTOUT(NUMBER); + } +0{D}+{IS}? { scale = 8; goto num; } +{D}+{IS}? { scale = 10; goto num; } +'(\\.|[^\\'])+' { + if (YYSTATE || slow) { + yylval.node.op = NUMBER; + yylval.node.nd_val = charcon((usch *)yytext); + return (NUMBER); + } + if (tflag) + yyless(1); + if (!flslvl) + putstr((usch *)yytext); + } + +. { return yytext[0]; } + +{D}+{E}{FS}? { PRTOUT(FPOINT); } +{D}*"."{D}+({E})?{FS}? { PRTOUT(FPOINT); } +{D}+"."{D}*({E})?{FS}? { PRTOUT(FPOINT); } + +^{WS}*#{WS}* { extern int inmac; + + if (inmac) + error("preprocessor directive found " + "while expanding macro"); + contr = 1; + BEGIN CONTR; + } +{WS}+ { PRTOUT(WSPACE); } + +"ifndef" { contr = 0; ifndefstmt(); } +"ifdef" { contr = 0; ifdefstmt(); } +"if" { contr = 0; storepb(); BEGIN IFR; ifstmt(); BEGIN 0; } +"include" { contr = 0; BEGIN 0; include(); prtline(); } +"else" { contr = 0; elsestmt(); } +"endif" { contr = 0; endifstmt(); } +"error" { contr = 0; if (slow) return IDENT; cpperror(); BEGIN 0; } +"define" { contr = 0; BEGIN DEF; define(); BEGIN 0; } +"undef" { contr = 0; if (slow) return IDENT; undefstmt(); } +"line" { contr = 0; storepb(); BEGIN 0; line(); } +"pragma" { contr = 0; pragmastmt(); BEGIN 0; } +"elif" { contr = 0; storepb(); BEGIN IFR; elifstmt(); BEGIN 0; } + + + +"//".*$ { /* if (tflag) yyless(..) */ + if (Cflag && !flslvl && !slow) + putstr((usch *)yytext); + else if (!flslvl) + putch(' '); + } +"/*" { int c, wrn; + int prtcm = Cflag && !flslvl && !slow; + extern int readmac; + + if (Cflag && !flslvl && readmac) + return CMNT; + + if (prtcm) + putstr((usch *)yytext); + wrn = 0; + more: while ((c = input()) && c != '*') { + if (c == '\n') + putch(c), ifiles->lineno++; + else if (c == 1) /* WARN */ + wrn = 1; + else if (prtcm) + putch(c); + } + if (c == 0) + return 0; + if (prtcm) + putch(c); + if ((c = input()) && c != '/') { + unput(c); + goto more; + } + if (prtcm) + putch(c); + if (c == 0) + return 0; + if (!tflag && !Cflag && !flslvl) + unput(' '); + if (wrn) + unput(1); + } + +"##" { return CONCAT; } +"#" { return MKSTR; } +"..." { return ELLIPS; } +"__VA_ARGS__" { return VA_ARGS; } + +L?\"(\\.|[^\\"])*\" { PRTOUT(STRING); } +[a-zA-Z_0-9]+ { /* {L}({L}|{D})* */ + struct symtab *nl; + if (slow) + return IDENT; + if (YYSTATE == CONTR) { + if (flslvl == 0) { + /*error("undefined control");*/ + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + goto xx; + } else { + BEGIN 0; /* do nothing */ + } + } + if (flslvl) { + ; /* do nothing */ + } else if (isdigit((int)yytext[0]) == 0 && + (nl = lookup((usch *)yytext, FIND)) != 0) { + usch *op = stringbuf; + putstr(gotident(nl)); + stringbuf = op; + } else + putstr((usch *)yytext); + xx: ; + } + +. { + if (contr) { + while (input() != '\n') + ; + unput('\n'); + BEGIN 0; + contr = 0; + goto yy; + } + if (YYSTATE || slow) + return yytext[0]; + if (yytext[0] == 6) { /* PRAGS */ + usch *obp = stringbuf; + extern usch *prtprag(usch *); + *stringbuf++ = yytext[0]; + do { + *stringbuf = input(); + } while (*stringbuf++ != 14); + prtprag(obp); + stringbuf = obp; + } else { + PRTOUT(yytext[0]); + } + yy:; + } + +%% + +usch *yyp, yybuf[CPPBUF]; + +int yylex(void); +int yywrap(void); + +static int +inpch(void) +{ + int len; + + if (ifiles->curptr < ifiles->maxread) + return *ifiles->curptr++; + + if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0) + error("read error on file %s", ifiles->orgfn); + if (len == 0) + return -1; + ifiles->curptr = ifiles->buffer; + ifiles->maxread = ifiles->buffer + len; + return inpch(); +} + +#define unch(c) *--ifiles->curptr = c + +static int +inch(void) +{ + int c; + +again: switch (c = inpch()) { + case '\\': /* continued lines */ +msdos: if ((c = inpch()) == '\n') { + ifiles->lineno++; + putch('\n'); + goto again; + } else if (c == '\r') + goto msdos; + unch(c); + return '\\'; + case '?': /* trigraphs */ + if ((c = inpch()) != '?') { + unch(c); + return '?'; + } + switch (c = inpch()) { + case '=': c = '#'; break; + case '(': c = '['; break; + case ')': c = ']'; break; + case '<': c = '{'; break; + case '>': c = '}'; break; + case '/': c = '\\'; break; + case '\'': c = '^'; break; + case '!': c = '|'; break; + case '-': c = '~'; break; + default: + unch(c); + unch('?'); + return '?'; + } + unch(c); + goto again; + default: + return c; + } +} + +/* + * Let the command-line args be faked defines at beginning of file. + */ +static void +prinit(struct initar *it, struct includ *ic) +{ + char *a, *pre, *post; + + if (it->next) + prinit(it->next, ic); + pre = post = NULL; /* XXX gcc */ + switch (it->type) { + case 'D': + pre = "#define "; + if ((a = strchr(it->str, '=')) != NULL) { + *a = ' '; + post = "\n"; + } else + post = " 1\n"; + break; + case 'U': + pre = "#undef "; + post = "\n"; + break; + case 'i': + pre = "#include \""; + post = "\"\n"; + break; + default: + error("prinit"); + } + strlcat((char *)ic->buffer, pre, CPPBUF+1); + strlcat((char *)ic->buffer, it->str, CPPBUF+1); + if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1) + error("line exceeds buffer size"); + + ic->lineno--; + while (*ic->maxread) + ic->maxread++; +} + +/* + * A new file included. + * If ifiles == NULL, this is the first file and already opened (stdin). + * Return 0 on success, -1 if file to be included is not found. + */ +int +pushfile(usch *file) +{ + extern struct initar *initar; + struct includ ibuf; + struct includ *ic; + int c, otrulvl; + + ic = &ibuf; + ic->next = ifiles; + + slow = 0; + if (file != NULL) { + if ((ic->infil = open((char *)file, O_RDONLY)) < 0) + return -1; + ic->orgfn = ic->fname = file; + if (++inclevel > MAX_INCLEVEL) + error("Limit for nested includes exceeded"); + } else { + ic->infil = 0; + ic->orgfn = ic->fname = (usch *)""; + } + ic->buffer = ic->bbuf+NAMEMAX; + ic->curptr = ic->buffer; + ifiles = ic; + ic->lineno = 1; + ic->maxread = ic->curptr; + prtline(); + if (initar) { + *ic->maxread = 0; + prinit(initar, ic); + if (dMflag) + write(ofd, ic->buffer, strlen((char *)ic->buffer)); + initar = NULL; + } + + otrulvl = trulvl; + + if ((c = yylex()) != 0) + error("yylex returned %d", c); + + if (otrulvl != trulvl || flslvl) + error("unterminated conditional"); + + ifiles = ic->next; + close(ic->infil); + inclevel--; + return 0; +} + +/* + * Print current position to output file. + */ +void +prtline() +{ + usch *s, *os = stringbuf; + + if (Mflag) { + if (dMflag) + return; /* no output */ + if (ifiles->lineno == 1) { + s = sheap("%s: %s\n", Mfile, ifiles->fname); + write(ofd, s, strlen((char *)s)); + } + } else if (!Pflag) + putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); + stringbuf = os; +} + +void +cunput(int c) +{ +#ifdef CPP_DEBUG + extern int dflag; + if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +#endif + unput(c); +} + +int yywrap(void) { return 1; } + +static int +dig2num(int c) +{ + if (c >= 'a') + c = c - 'a' + 10; + else if (c >= 'A') + c = c - 'A' + 10; + else + c = c - '0'; + return c; +} + +/* + * Convert string numbers to unsigned long long and check overflow. + */ +static void +cvtdig(int rad) +{ + unsigned long long rv = 0; + unsigned long long rv2 = 0; + char *y = yytext; + int c; + + c = *y++; + if (rad == 16) + y++; + while (isxdigit(c)) { + rv = rv * rad + dig2num(c); + /* check overflow */ + if (rv / rad < rv2) + error("Constant \"%s\" is out of range", yytext); + rv2 = rv; + c = *y++; + } + y--; + while (*y == 'l' || *y == 'L') + y++; + yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER; + yylval.node.nd_uval = rv; + if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0) + yylval.node.op = UNUMBER; + if (yylval.node.op == NUMBER && yylval.node.nd_val < 0) + /* too large for signed */ + error("Constant \"%s\" is out of range", yytext); +} + +static int +charcon(usch *p) +{ + int val, c; + + p++; /* skip first ' */ + val = 0; + if (*p++ == '\\') { + switch (*p++) { + case 'a': val = '\a'; break; + case 'b': val = '\b'; break; + case 'f': val = '\f'; break; + case 'n': val = '\n'; break; + case 'r': val = '\r'; break; + case 't': val = '\t'; break; + case 'v': val = '\v'; break; + case '\"': val = '\"'; break; + case '\'': val = '\''; break; + case '\\': val = '\\'; break; + case 'x': + while (isxdigit(c = *p)) { + val = val * 16 + dig2num(c); + p++; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + p--; + while (isdigit(c = *p)) { + val = val * 8 + (c - '0'); + p++; + } + break; + default: val = p[-1]; + } + + } else + val = p[-1]; + return val; +} + +static void +chknl(int ignore) +{ + int t; + + slow = 1; + while ((t = yylex()) == WSPACE) + ; + if (t != '\n') { + if (ignore) { + warning("newline expected, got \"%s\"", yytext); + /* ignore rest of line */ + while ((t = yylex()) && t != '\n') + ; + } + else + error("newline expected, got \"%s\"", yytext); + } + slow = 0; +} + +static void +elsestmt(void) +{ + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) { + flslvl++; + } else { + trulvl++; + prtline(); + } + } else if (trulvl) { + flslvl++; + trulvl--; + } else + error("If-less else"); + if (elslvl==trulvl+flslvl) + error("Too many else"); + elslvl=trulvl+flslvl; + chknl(1); +} + +static void +ifdefstmt(void) +{ + int t; + + if (flslvl) { + /* just ignore the rest of the line */ + while (input() != '\n') + ; + unput('\n'); + yylex(); + flslvl++; + return; + } + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifdef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) != 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +ifndefstmt(void) +{ + int t; + + slow = 1; + do + t = yylex(); + while (t == WSPACE); + if (t != IDENT) + error("bad ifndef"); + slow = 0; + if (flslvl == 0 && lookup((usch *)yytext, FIND) == 0) + trulvl++; + else + flslvl++; + chknl(0); +} + +static void +endifstmt(void) +{ + if (flslvl) { + flslvl--; + if (flslvl == 0) + prtline(); + } else if (trulvl) + trulvl--; + else + error("If-less endif"); + if (flslvl == 0) + elflvl = 0; + elslvl = 0; + chknl(1); +} + +/* + * Note! Ugly! + * Walk over the string s and search for defined, and replace it with + * spaces and a 1 or 0. + */ +static void +fixdefined(usch *s) +{ + usch *bc, oc; + + for (; *s; s++) { + if (*s != 'd') + continue; + if (memcmp(s, "defined", 7)) + continue; + /* Ok, got defined, can scratch it now */ + memset(s, ' ', 7); + s += 7; +#define WSARG(x) (x == ' ' || x == '\t') + if (*s != '(' && !WSARG(*s)) + continue; + while (WSARG(*s)) + s++; + if (*s == '(') + s++; + while (WSARG(*s)) + s++; +#define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_')) +#define NUMARG(x) (x >= '0' && x <= '9') + if (!IDARG(*s)) + error("bad defined arg"); + bc = s; + while (IDARG(*s) || NUMARG(*s)) + s++; + oc = *s; + *s = 0; + *bc = (lookup(bc, FIND) != 0) + '0'; + memset(bc+1, ' ', s-bc-1); + *s = oc; + } +} + +/* + * get the full line of identifiers after an #if, pushback a WARN and + * the line and prepare for expmac() to expand. + * This is done before switching state. When expmac is finished, + * pushback the expanded line, change state and call yyparse. + */ +static void +storepb(void) +{ + usch *opb = stringbuf; + int c; + + while ((c = input()) != '\n') { + if (c == '/') { + if ((c = input()) == '*') { + /* ignore comments here whatsoever */ + usch *g = stringbuf; + getcmnt(); + stringbuf = g; + continue; + } else if (c == '/') { + while ((c = input()) && c != '\n') + ; + break; + } + unput(c); + c = '/'; + } + savch(c); + } + cunput('\n'); + savch(0); + fixdefined(opb); /* XXX can fail if #line? */ + cunput(1); /* WARN XXX */ + unpstr(opb); + stringbuf = opb; + slow = 1; + expmac(NULL); + slow = 0; + /* line now expanded */ + while (stringbuf > opb) + cunput(*--stringbuf); +} + +static void +ifstmt(void) +{ + if (flslvl == 0) { + slow = 1; + if (yyparse()) + ++trulvl; + else + ++flslvl; + slow = 0; + } else + ++flslvl; +} + +static void +elifstmt(void) +{ + if (flslvl == 0) + elflvl = trulvl; + if (flslvl) { + if (elflvl > trulvl) + ; + else if (--flslvl!=0) + ++flslvl; + else { + slow = 1; + if (yyparse()) { + ++trulvl; + prtline(); + } else + ++flslvl; + slow = 0; + } + } else if (trulvl) { + ++flslvl; + --trulvl; + } else + error("If-less elif"); +} + +static usch * +svinp(void) +{ + int c; + usch *cp = stringbuf; + + while ((c = input()) && c != '\n') + savch(c); + savch('\n'); + savch(0); + BEGIN 0; + return cp; +} + +static void +cpperror(void) +{ + usch *cp; + int c; + + if (flslvl) + return; + c = yylex(); + if (c != WSPACE && c != '\n') + error("bad error"); + cp = svinp(); + if (flslvl) + stringbuf = cp; + else + error("%s", cp); +} + +static void +undefstmt(void) +{ + struct symtab *np; + + slow = 1; + if (yylex() != WSPACE || yylex() != IDENT) + error("bad undef"); + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) + np->value = 0; + slow = 0; + chknl(0); +} + +static void +pragmastmt(void) +{ + int c; + + slow = 1; + if (yylex() != WSPACE) + error("bad pragma"); + if (!flslvl) + putstr((usch *)"#pragma "); + do { + c = input(); + if (!flslvl) + putch(c); /* Do arg expansion instead? */ + } while (c && c != '\n'); + ifiles->lineno++; + prtline(); + slow = 0; +} + +static void +badop(const char *op) +{ + error("invalid operator in preprocessor expression: %s", op); +} + +int +cinput() +{ + return input(); +} diff --git a/src/cmd/cpp/tests/res11 b/src/cmd/cpp/tests/res11 new file mode 100644 index 0000000..4c49d18 --- /dev/null +++ b/src/cmd/cpp/tests/res11 @@ -0,0 +1,22 @@ + +# 1 "" + + + + + +a +a b +a b c +a b c d + + + + + + +__attribute__((__noreturn__)) + + +1 2 + diff --git a/src/cmd/cpp/tests/res12 b/src/cmd/cpp/tests/res12 new file mode 100644 index 0000000..1420d39 --- /dev/null +++ b/src/cmd/cpp/tests/res12 @@ -0,0 +1,21 @@ + +# 1 "" + + + + + +2 2 2 2 2; + + + + + + + + + + + + +(0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, (0 + 8) + 0, diff --git a/src/cmd/cpp/tests/res13 b/src/cmd/cpp/tests/res13 new file mode 100644 index 0000000..5ec9b41 --- /dev/null +++ b/src/cmd/cpp/tests/res13 @@ -0,0 +1,13 @@ + +# 1 "" + + + + +long + + + + + + diff --git a/src/cmd/cpp/tests/res2 b/src/cmd/cpp/tests/res2 index 945449b..e9fb624 100644 --- a/src/cmd/cpp/tests/res2 +++ b/src/cmd/cpp/tests/res2 @@ -15,7 +15,8 @@ f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & +f(2 * (0,1))^m(0,1); int i[] = { 1, 23, 4, 5, }; char c[2][6] = { "hello", "" }; diff --git a/src/cmd/cpp/tests/test11 b/src/cmd/cpp/tests/test11 new file mode 100644 index 0000000..5bf4249 --- /dev/null +++ b/src/cmd/cpp/tests/test11 @@ -0,0 +1,20 @@ +#define D1(s, ...) s +#define D2(s, ...) s D1(__VA_ARGS__) +#define D3(s, ...) s D2(__VA_ARGS__) +#define D4(s, ...) s D3(__VA_ARGS__) + +D1(a) +D2(a, b) +D3(a, b, c) +D4(a, b, c, d) + + +#define __sun_attr___noreturn__ __attribute__((__noreturn__)) +#define ___sun_attr_inner(__a) __sun_attr_##__a +#define __sun_attr__(__a) ___sun_attr_inner __a +#define __NORETURN __sun_attr__((__noreturn__)) +__NORETURN +#define X(...) +#define Y(...) 1 __VA_ARGS__ 2 +Y(X X() ()) + diff --git a/src/cmd/cpp/tests/test12 b/src/cmd/cpp/tests/test12 new file mode 100644 index 0000000..a0a36f1 --- /dev/null +++ b/src/cmd/cpp/tests/test12 @@ -0,0 +1,19 @@ +#define y 2 +#define fe(p) sfe(p) p +#define sfe(p) p +#define Y fe(y) y fe(y) + +Y; + +# define S2B_QMIN 0 +# define S2B_CMIN (S2B_QMIN + 8) +#define S2B_1(i) i, +#define S2B_2(i) S2B_1(i) S2B_1(i) +#define S2B_4(i) S2B_2(i) S2B_2(i) +#define S2B_8(i) S2B_4(i) S2B_4(i) +#define S2B_16(i) S2B_8(i) S2B_8(i) +#define S2B_32(i) S2B_16(i) S2B_16(i) +#define S2B_64(i) S2B_32(i) S2B_32(i) +#define S2B_128(i) S2B_64(i) S2B_64(i) +#define S2B_256(i) S2B_128(i) S2B_128(i) +S2B_256(S2B_CMIN + 0) diff --git a/src/cmd/cpp/tests/test13 b/src/cmd/cpp/tests/test13 new file mode 100644 index 0000000..51e2385 --- /dev/null +++ b/src/cmd/cpp/tests/test13 @@ -0,0 +1,11 @@ + +#define UL long, foo +#define D(I,F) I +#define E(I) D(I) +E(UL) + +#define FOO 1 + +#if (FOO == 1) + +#endif /* FOO */ diff --git a/src/cmd/cpp/token.c b/src/cmd/cpp/token.c index aeac691..e6e6d96 100644 --- a/src/cmd/cpp/token.c +++ b/src/cmd/cpp/token.c @@ -1,3 +1,5 @@ +/* $Id: token.c,v 1.48.2.2 2011/03/12 17:08:26 ragge Exp $ */ + /* * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved. * @@ -37,21 +39,24 @@ * - inch() is like inpch but \\n and trigraphs are expanded. * - unch() pushes back a character to the input stream. */ -#ifdef CROSS -# include -#else -# include -#endif + +#include "config.h" + #include +#include +#include +#ifdef HAVE_UNISTD_H #include +#endif #include #include +#include "compat.h" #include "cpp.h" #include "y.tab.h" static void cvtdig(int rad); -static int charcon(uchar *); +static int charcon(usch *); static void elsestmt(void); static void ifdefstmt(void); static void ifndefstmt(void); @@ -75,9 +80,8 @@ extern void yyset_lineno (int); static int inch(void); -size_t strlcat(char *dst, const char *src, size_t siz); - int inif; +extern int dflag; #define PUTCH(ch) if (!flslvl) putch(ch) /* protection against recursion in #include */ @@ -87,25 +91,16 @@ static int inclevel; /* get next character unaltered */ #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch()) -#ifdef YYTEXT_POINTER -static char buf[CPPBUF]; -char *yytext = buf; -#else -char yytext[CPPBUF]; -#endif +usch yytext[CPPBUF]; -#define C_SPEC 1 -#define C_EP 2 -#define C_ID 4 -#define C_I (C_SPEC|C_ID) -#define C_2 8 /* for yylex() tokenizing */ -static const char spechr[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, C_SPEC, 0, 0, 0, 0, 0, +char spechr[256] = { + 0, 0, 0, 0, C_SPEC, C_SPEC, 0, 0, + 0, C_WSNL, C_SPEC|C_WSNL, 0, + 0, C_WSNL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, + C_WSNL, C_2, C_SPEC, 0, 0, 0, C_2, C_SPEC, 0, 0, 0, C_2, 0, C_2, 0, C_SPEC|C_2, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, C_I, 0, 0, C_2, C_2, C_2, C_SPEC, @@ -122,14 +117,55 @@ static const char spechr[256] = { }; +/* + * No-replacement array. If a macro is found and exists in this array + * then no replacement shall occur. This is a stack. + */ +struct symtab *norep[RECMAX]; /* Symbol table index table */ +int norepptr = 1; /* Top of index table */ +unsigned short bptr[RECMAX]; /* currently active noexpand macro stack */ +int bidx; /* Top of bptr stack */ + static void unch(int c) { - + --ifiles->curptr; if (ifiles->curptr < ifiles->bbuf) error("pushback buffer full"); - *ifiles->curptr = (uchar)c; + *ifiles->curptr = (usch)c; +} + +static int +eatcmnt(void) +{ + int ch; + + if (Cflag) { PUTCH('/'); PUTCH('*'); } + for (;;) { + ch = inch(); + if (ch == '\n') { + ifiles->lineno++; + PUTCH('\n'); + } + if (ch == -1) + return -1; + if (ch == '*') { + ch = inch(); + if (ch == '/') { + if (Cflag) { + PUTCH('*'); + PUTCH('/'); + } else + PUTCH(' '); + break; + } + unch(ch); + ch = '*'; + } + if (Cflag) PUTCH(ch); + } + return 0; } /* @@ -146,51 +182,38 @@ static void fastscan(void) { struct symtab *nl; - int ch, i; + int ch, i, ccnt/*, onemore*/; + usch *cp; goto run; for (;;) { ch = NXTCH(); xloop: if (ch == -1) return; + if (dflag>1) + printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@'); if ((spechr[ch] & C_SPEC) == 0) { PUTCH(ch); continue; } switch (ch) { + case EBLOCK: + case WARN: + case CONC: + error("bad char passed"); + break; + case '/': /* Comments */ if ((ch = inch()) == '/') { - if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } +cppcmt: if (Cflag) { PUTCH(ch); } else { PUTCH(' '); } do { if (Cflag) PUTCH(ch); ch = inch(); } while (ch != -1 && ch != '\n'); goto xloop; } else if (ch == '*') { - if (Cflag) { PUTCH('/'); PUTCH('*'); } - for (;;) { - ch = inch(); - if (ch == '\n') { - ifiles->lineno++; - PUTCH('\n'); - } - if (ch == -1) - return; - if (ch == '*') { - ch = inch(); - if (ch == '/') { - if (Cflag) { - PUTCH('*'); - PUTCH('/'); - } else - PUTCH(' '); - break; - } - unch(ch); - ch = '*'; - } - if (Cflag) PUTCH(ch); - } + if (eatcmnt()) + return; } else { PUTCH('/'); goto xloop; @@ -213,11 +236,30 @@ xloop: if (ch == -1) goto xloop; case '\n': /* newlines, for pp directives */ - ifiles->lineno++; +run2: ifiles->lineno++; do { PUTCH(ch); run: ch = NXTCH(); + if (ch == '/') { + ch = NXTCH(); + if (ch == '/') + goto cppcmt; + if (ch == '*') { + if (eatcmnt()) + return; + goto run; + } + unch(ch); + ch = '/'; + } } while (ch == ' ' || ch == '\t'); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') + goto run2; + unch(ch); + ch = '\\'; + } if (ch == '#') { ppdir(); continue; @@ -236,7 +278,7 @@ run: ch = NXTCH(); case '\"': /* strings */ str: PUTCH(ch); while ((ch = inch()) != '\"') { - PUTCH(ch); + PUTCH(ch); if (ch == '\\') { ch = inch(); PUTCH(ch); @@ -257,7 +299,16 @@ str: PUTCH(ch); case '5': case '6': case '7': case '8': case '9': do { PUTCH(ch); - ch = NXTCH(); +nxt: ch = NXTCH(); + if (ch == '\\') { + ch = NXTCH(); + if (ch == '\n') { + goto nxt; + } else { + unch(ch); + ch = '\\'; + } + } if (spechr[ch] & C_EP) { PUTCH(ch); ch = NXTCH(); @@ -305,9 +356,9 @@ con: PUTCH(ch); ch = NXTCH(); goto xloop; } - i = 0; + /*onemore =*/ i = ccnt = 0; do { - yytext[i++] = (uchar)ch; + yytext[i++] = (usch)ch; ch = NXTCH(); if (ch == '\\') { ch = NXTCH(); @@ -322,14 +373,17 @@ con: PUTCH(ch); if (ch < 0) return; } while (spechr[ch] & C_ID); + yytext[i] = 0; unch(ch); - if ((nl = lookup((uchar *)yytext, FIND)) != 0) { - uchar *op = stringbuf; - putstr(gotident(nl)); - stringbuf = op; + + cp = stringbuf; + if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) { + putstr(stringbuf); } else - putstr((uchar *)yytext); + putstr((usch *)yytext); + stringbuf = cp; + break; } } @@ -344,7 +398,7 @@ sloscan() zagain: yyp = 0; ch = inch(); - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; switch (ch) { case -1: return 0; @@ -357,24 +411,24 @@ zagain: yyp = 0; break; - case '0': case '1': case '2': case '3': case '4': case '5': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* readin a "pp-number" */ ppnum: for (;;) { ch = inch(); if (spechr[ch] & C_EP) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); if (ch == '-' || ch == '+') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else unch(ch); continue; } if ((spechr[ch] & C_ID) || ch == '.') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; continue; - } + } break; } unch(ch); @@ -383,11 +437,11 @@ ppnum: for (;;) { return NUMBER; case '\'': -chlit: +chlit: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; } else if (ch == '\n') { /* not a constant */ @@ -396,7 +450,7 @@ chlit: ch = '\''; goto any; } else - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; if (ch == '\'') break; } @@ -407,7 +461,7 @@ chlit: case ' ': case '\t': while ((ch = inch()) == ' ' || ch == '\t') - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; unch(ch); yytext[yyp] = 0; return(WSPACE); @@ -415,7 +469,7 @@ chlit: case '/': if ((ch = inch()) == '/') { do { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; ch = inch(); } while (ch && ch != '\n'); yytext[yyp] = 0; @@ -435,7 +489,10 @@ chlit: more: while ((c = inch()) && c != '*') { if (c == '\n') putch(c), ifiles->lineno++; - else if (c == 1) /* WARN */ + else if (c == EBLOCK) { + (void)inch(); + (void)inch(); + } else if (c == 1) /* WARN */ wrn = 1; } if (c == 0) @@ -459,7 +516,7 @@ chlit: case '.': ch = inch(); if (isdigit(ch)) { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; goto ppnum; } else { unch(ch); @@ -468,14 +525,16 @@ chlit: goto any; case '\"': + if (tflag) + goto any; strng: for (;;) { if ((ch = inch()) == '\\') { - yytext[yyp++] = (uchar)ch; - yytext[yyp++] = (uchar)inch(); + yytext[yyp++] = (usch)ch; + yytext[yyp++] = (usch)inch(); continue; - } else - yytext[yyp++] = (uchar)ch; + } else + yytext[yyp++] = (usch)ch; if (ch == '\"') break; } @@ -483,26 +542,26 @@ chlit: return(STRING); case 'L': - if ((ch = inch()) == '\"') { - yytext[yyp++] = (uchar)ch; + if ((ch = inch()) == '\"' && !tflag) { + yytext[yyp++] = (usch)ch; goto strng; - } else if (ch == '\'') { - yytext[yyp++] = (uchar)ch; + } else if (ch == '\'' && !tflag) { + yytext[yyp++] = (usch)ch; goto chlit; } unch(ch); /* FALLTHROUGH */ /* Yetch, all identifiers */ - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': - case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': - case 's': case 't': case 'u': case 'v': case 'w': case 'x': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': + case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': + case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': + case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': /* {L}({L}|{D})* */ @@ -510,7 +569,7 @@ chlit: for (;;) { /* get chars */ ch = inch(); if (isalpha(ch) || isdigit(ch) || ch == '_') { - yytext[yyp++] = (uchar)ch; + yytext[yyp++] = (usch)ch; } else { unch(ch); break; @@ -584,27 +643,31 @@ yylex() case NUMBER: if (yytext[0] == '\'') { yylval.node.op = NUMBER; - yylval.node.nd_val = charcon((uchar *)yytext); + yylval.node.nd_val = charcon((usch *)yytext); } else cvtdig(yytext[0] != '0' ? 10 : yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8); return NUMBER; case IDENT: - if (strcmp(yytext, "defined") == 0) { + if (strcmp((char *)yytext, "defined") == 0) { ifdef = 1; return DEFINED; } - nl = lookup((uchar *)yytext, FIND); + nl = lookup((usch *)yytext, FIND); if (ifdef) { yylval.node.nd_val = nl != NULL; ifdef = 0; } else if (nl && noex == 0) { - uchar *c, *och = stringbuf; + usch *och = stringbuf; + int i; - c = gotident(nl); - unch(1); - unpstr(c); + i = kfind(nl); + unch(WARN); + if (i) + unpstr(stringbuf); + else + unpstr(nl->namep); stringbuf = och; noex = 1; return yylex(); @@ -613,7 +676,7 @@ yylex() } yylval.node.op = NUMBER; return NUMBER; - case 1: /* WARN */ + case WARN: noex = 0; return yylex(); default: @@ -623,7 +686,7 @@ yylex() return ch; } -uchar *yyp, yybuf[CPPBUF]; +usch *yyp, yybuf[CPPBUF]; int yywrap(void); @@ -671,41 +734,6 @@ msdos: if ((c = inpch()) == '\n') { } } -/* - * Appends src to string dst of size siz (unlike strncat, siz is the - * full size of dst, not space left). At most siz-1 characters - * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(initial dst) + strlen(src); if retval >= siz, - * truncation occurred. - */ -size_t -strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ -} - /* * Let the command-line args be faked defines at beginning of file. */ @@ -754,30 +782,29 @@ prinit(struct initar *it, struct includ *ic) * Return 0 on success, -1 if file to be included is not found. */ int -pushfile(const uchar *file, const uchar *fn, int idx, void *incs) +pushfile(const usch *file, const usch *fn, int idx, void *incs) { extern struct initar *initar; + struct includ ibuf; struct includ *ic; int otrulvl; - ic = malloc(sizeof(struct includ)); - if (ic == NULL) - error("out of memory for %s", file); + ic = &ibuf; ic->next = ifiles; if (file != NULL) { - ic->infil = open((const char *)file, O_RDONLY); - if (ic->infil < 0) { - free(ic); + if ((ic->infil = open((const char *)file, O_RDONLY)) < 0) return -1; - } ic->orgfn = ic->fname = file; if (++inclevel > MAX_INCLEVEL) error("Limit for nested includes exceeded"); } else { ic->infil = 0; - ic->orgfn = ic->fname = (const uchar *)""; + ic->orgfn = ic->fname = (const usch *)""; } +#ifndef BUF_STACK + ic->bbuf = malloc(BBUFSZ); +#endif ic->buffer = ic->bbuf+NAMEMAX; ic->curptr = ic->buffer; ifiles = ic; @@ -794,8 +821,7 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) prinit(initar, ic); initar = NULL; if (dMflag) - if (write(ofd, ic->buffer, strlen((char *)ic->buffer)) < 0) - /* ignore */; + write(ofd, ic->buffer, strlen((char *)ic->buffer)); fastscan(); prtline(); ic->infil = oin; @@ -808,9 +834,11 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) if (otrulvl != trulvl || flslvl) error("unterminated conditional"); +#ifndef BUF_STACK + free(ic->bbuf); +#endif ifiles = ic->next; close(ic->infil); - free(ic); inclevel--; return 0; } @@ -821,15 +849,14 @@ pushfile(const uchar *file, const uchar *fn, int idx, void *incs) void prtline() { - uchar *s, *os = stringbuf; + usch *s, *os = stringbuf; if (Mflag) { if (dMflag) return; /* no output */ if (ifiles->lineno == 1) { s = sheap("%s: %s\n", Mfile, ifiles->fname); - if (write(ofd, s, strlen((char *)s)) < 0) - /* ignore */; + write(ofd, s, strlen((char *)s)); } } else if (!Pflag) putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname)); @@ -840,8 +867,8 @@ void cunput(int c) { #ifdef CPP_DEBUG - extern int dflag; - if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c); +// extern int dflag; +// if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c); #endif #if 0 if (c == 10) { @@ -873,7 +900,7 @@ cvtdig(int rad) { unsigned long long rv = 0; unsigned long long rv2 = 0; - char *y = yytext; + usch *y = yytext; int c; c = *y++; @@ -900,7 +927,7 @@ cvtdig(int rad) } static int -charcon(uchar *p) +charcon(usch *p) { int val, c; @@ -993,8 +1020,8 @@ skpln(void) } static void -ifdefstmt(void) -{ +ifdefstmt(void) +{ int t; if (flslvl) { @@ -1006,7 +1033,7 @@ ifdefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifdef"); - if (lookup((uchar *)yytext, FIND) == 0) { + if (lookup((usch *)yytext, FIND) == 0) { putch('\n'); flslvl++; } else @@ -1015,8 +1042,8 @@ ifdefstmt(void) } static void -ifndefstmt(void) -{ +ifndefstmt(void) +{ int t; if (flslvl) { @@ -1028,7 +1055,7 @@ ifndefstmt(void) while (t == WSPACE); if (t != IDENT) error("bad ifndef"); - if (lookup((uchar *)yytext, FIND) != 0) { + if (lookup((usch *)yytext, FIND) != 0) { putch('\n'); flslvl++; } else @@ -1037,7 +1064,7 @@ ifndefstmt(void) } static void -endifstmt(void) +endifstmt(void) { if (flslvl) { flslvl--; @@ -1094,11 +1121,11 @@ elifstmt(void) error("If-less elif"); } -static uchar * +static usch * svinp(void) { int c; - uchar *cp = stringbuf; + usch *cp = stringbuf; while ((c = inch()) && c != '\n') savch(c); @@ -1110,7 +1137,7 @@ svinp(void) static void cpperror(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1128,7 +1155,7 @@ cpperror(void) static void cppwarning(void) { - uchar *cp; + usch *cp; int c; if (flslvl) @@ -1158,7 +1185,7 @@ undefstmt(void) if (sloscan() != WSPACE || sloscan() != IDENT) error("bad undef"); - if (flslvl == 0 && (np = lookup((uchar *)yytext, FIND))) + if (flslvl == 0 && (np = lookup((usch *)yytext, FIND))) np->value = 0; chknl(0); } @@ -1171,7 +1198,7 @@ pragmastmt(void) if (sloscan() != WSPACE) error("bad pragma"); if (!flslvl) - putstr((const uchar *)"#pragma "); + putstr((const usch *)"\n#pragma "); do { c = inch(); if (!flslvl) @@ -1265,7 +1292,7 @@ ppdir(void) goto out; /* something else, ignore */ i = 0; do { - bp[i++] = (uchar)ch; + bp[i++] = (usch)ch; if (i == sizeof(bp)-1) goto out; /* too long */ ch = inch(); From 91468f005f1257b28458ffee564fc93947550227 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 16 May 2014 17:59:53 -0700 Subject: [PATCH 04/40] Fixed build and simulator configuration for Explorer1 board. --- sys/pic32/explorer16/.gitignore | 1 + sys/pic32/kernel-post.mk | 4 +++- tools/virtualmips/Makefile | 3 +++ tools/virtualmips/pic32_explorer16.conf | 13 ++++++++++--- tools/virtualmips/pic32_max32.conf | 4 ++-- tools/virtualmips/pic32_maximite.conf | 2 +- tools/virtualmips/pic32_ubw32.conf | 2 +- 7 files changed, 21 insertions(+), 8 deletions(-) diff --git a/sys/pic32/explorer16/.gitignore b/sys/pic32/explorer16/.gitignore index 6a22af6..2b28c2d 100644 --- a/sys/pic32/explorer16/.gitignore +++ b/sys/pic32/explorer16/.gitignore @@ -4,6 +4,7 @@ machine sys unix.bin +boot.bin unix.map usbboot.map vers.c diff --git a/sys/pic32/kernel-post.mk b/sys/pic32/kernel-post.mk index b73fd0e..5f161c8 100644 --- a/sys/pic32/kernel-post.mk +++ b/sys/pic32/kernel-post.mk @@ -40,7 +40,9 @@ unix.elf: $(KERNOBJ) $(LDSCRIPT) $(CC) $(LDFLAGS) $(KERNOBJ) -o $@ chmod -x $@ $(OBJDUMP) -d -S $@ > unix.dis - $(OBJCOPY) -O binary $@ unix.bin + $(OBJCOPY) -O binary -R .boot -R .config $@ unix.bin + $(OBJCOPY) -O binary -j .boot -j .config $@ boot.bin + test -s boot.bin || rm boot.bin $(OBJCOPY) -O ihex --change-addresses=0x80000000 $@ unix.hex chmod -x $@ unix.bin diff --git a/tools/virtualmips/Makefile b/tools/virtualmips/Makefile index ad1f9db..46ae104 100644 --- a/tools/virtualmips/Makefile +++ b/tools/virtualmips/Makefile @@ -6,6 +6,9 @@ # chipKIT Max32 CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DMAX32 +# Maximite +#CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DMAXIMITE + # Microchip Explorer 16 #CFLAGS = -DSIM_PIC32 -DPIC32MX7 -DEXPLORER16 diff --git a/tools/virtualmips/pic32_explorer16.conf b/tools/virtualmips/pic32_explorer16.conf index fbde208..211e9d0 100644 --- a/tools/virtualmips/pic32_explorer16.conf +++ b/tools/virtualmips/pic32_explorer16.conf @@ -16,14 +16,21 @@ flash_size = 492 # kbytes flash_phy_address = 0x1d000000 flash_file_name = ../../sys/pic32/explorer16/unix.bin -start_address = 0x9d001000 # user program +# +# Boot flash +# +boot_flash_size = 12 # kbytes +boot_flash_address = 0x1fc00000 +boot_file_name = ../../sys/pic32/explorer16/boot.bin + +start_address = 0x9fc00000 # user program # # SD/MMC cards # sdcard_port = 1 # SPI1 -sdcard0_size = 16 # Mbytes -sdcard0_file_name = ../../filesys.img +sdcard0_size = 340 # Mbytes +sdcard0_file_name = ../../sdcard.rd # # UARTs 1..6 diff --git a/tools/virtualmips/pic32_max32.conf b/tools/virtualmips/pic32_max32.conf index 2bce54f..b962fa1 100644 --- a/tools/virtualmips/pic32_max32.conf +++ b/tools/virtualmips/pic32_max32.conf @@ -28,7 +28,7 @@ sdcard0_file_name = ../../sdcard.rd # # UARTs 1..6 # -uart1_type = console +uart1_type = console # # Debug level: @@ -38,4 +38,4 @@ uart1_type = console # 3 - trace all inctructions # debug_level = 0 -#trace_address = 0x9d00720c +#trace_address = 0x9d00720c diff --git a/tools/virtualmips/pic32_maximite.conf b/tools/virtualmips/pic32_maximite.conf index 28e103d..8dcdc7f 100644 --- a/tools/virtualmips/pic32_maximite.conf +++ b/tools/virtualmips/pic32_maximite.conf @@ -22,7 +22,7 @@ start_address = 0x9d006000 # user program # SD/MMC cards # sdcard_port = 4 # SPI4 -sdcard0_size = 16 # Mbytes +sdcard0_size = 340 # Mbytes sdcard0_file_name = ../../filesys.img # diff --git a/tools/virtualmips/pic32_ubw32.conf b/tools/virtualmips/pic32_ubw32.conf index 2ccd87b..ab5649d 100644 --- a/tools/virtualmips/pic32_ubw32.conf +++ b/tools/virtualmips/pic32_ubw32.conf @@ -22,7 +22,7 @@ start_address = 0x9d006000 # user program # SD/MMC cards # sdcard_port = 1 # SPI1 -sdcard0_size = 16 # Mbytes +sdcard0_size = 340 # Mbytes sdcard0_file_name = ../../filesys.img #sdcard1_size = 2 # Mbytes #sdcard1_file_name = ../../home.img From 5bd8f3a470be65e2a1b4f25e979a26cba91fec5b Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 16 May 2014 20:44:53 -0700 Subject: [PATCH 05/40] Fixed sd timeout in the simulator. SD driver reformatted with 4 spaces per tab. --- sys/pic32/rd_sd.c | 390 ++++++++++++++++----------------- tools/virtualmips/dev_sdcard.c | 7 + 2 files changed, 202 insertions(+), 195 deletions(-) diff --git a/sys/pic32/rd_sd.c b/sys/pic32/rd_sd.c index 2634f37..8cd84f2 100644 --- a/sys/pic32/rd_sd.c +++ b/sys/pic32/rd_sd.c @@ -42,12 +42,12 @@ /* * Two SD/MMC disks on SPI. * Signals for SPI1: - * D0 - SDO1 - * D10 - SCK1 - * C4 - SDI1 + * D0 - SDO1 + * D10 - SCK1 + * C4 - SDI1 */ -#define NSD 2 -#define SECTSIZE 512 +#define NSD 2 +#define SECTSIZE 512 #define SPI_ENHANCED /* use SPI fifo */ #ifndef SD0_MHZ #define SD0_MHZ 13 /* speed 13.33 MHz */ @@ -82,23 +82,23 @@ int sd_timo_wait_widle; /* * Definitions for MMC/SDC commands. */ -#define CMD_GO_IDLE 0 /* CMD0 */ -#define CMD_SEND_OP_MMC 1 /* CMD1 (MMC) */ -#define CMD_SEND_IF_COND 8 -#define CMD_SEND_CSD 9 -#define CMD_SEND_CID 10 -#define CMD_STOP 12 -#define CMD_SEND_STATUS 13 /* CMD13 */ -#define CMD_SET_BLEN 16 -#define CMD_READ_SINGLE 17 -#define CMD_READ_MULTIPLE 18 -#define CMD_SET_BCOUNT 23 /* (MMC) */ -#define CMD_SET_WBECNT 23 /* ACMD23 (SDC) */ -#define CMD_WRITE_SINGLE 24 -#define CMD_WRITE_MULTIPLE 25 -#define CMD_SEND_OP_SDC 41 /* ACMD41 (SDC) */ -#define CMD_APP 55 /* CMD55 */ -#define CMD_READ_OCR 58 +#define CMD_GO_IDLE 0 /* CMD0 */ +#define CMD_SEND_OP_MMC 1 /* CMD1 (MMC) */ +#define CMD_SEND_IF_COND 8 +#define CMD_SEND_CSD 9 +#define CMD_SEND_CID 10 +#define CMD_STOP 12 +#define CMD_SEND_STATUS 13 /* CMD13 */ +#define CMD_SET_BLEN 16 +#define CMD_READ_SINGLE 17 +#define CMD_READ_MULTIPLE 18 +#define CMD_SET_BCOUNT 23 /* (MMC) */ +#define CMD_SET_WBECNT 23 /* ACMD23 (SDC) */ +#define CMD_WRITE_SINGLE 24 +#define CMD_WRITE_MULTIPLE 25 +#define CMD_SEND_OP_SDC 41 /* ACMD41 (SDC) */ +#define CMD_APP 55 /* CMD55 */ +#define CMD_READ_OCR 58 #define DATA_START_BLOCK 0xFE /* start data for single block */ #define STOP_TRAN_TOKEN 0xFD /* stop token for write multiple */ @@ -122,9 +122,9 @@ static void spi_wait_ready (int unit, int limit, int *maxcount) int i; spi_transfer(sd_fd[unit],0xFF); - for (i=0; i> 24); - spi_transfer(sd_fd[unit],addr >> 16); - spi_transfer(sd_fd[unit],addr >> 8); - spi_transfer(sd_fd[unit],addr); + /* Send a comand packet (6 bytes). */ + spi_transfer(sd_fd[unit],cmd | 0x40); + spi_transfer(sd_fd[unit],addr >> 24); + spi_transfer(sd_fd[unit],addr >> 16); + spi_transfer(sd_fd[unit],addr >> 8); + spi_transfer(sd_fd[unit],addr); - /* Send cmd checksum for CMD_GO_IDLE. + /* Send cmd checksum for CMD_GO_IDLE. * For all other commands, CRC is ignored. */ if (cmd == CMD_GO_IDLE) spi_transfer(sd_fd[unit],0x95); @@ -175,23 +175,23 @@ static int card_cmd(unsigned int unit, unsigned int cmd, unsigned int addr) else spi_transfer(sd_fd[unit],0xFF); - /* Wait for a response. */ - for (i=0; i= TIMO_SEND_OP) + spi_select(sd_fd[unit]); + if (reply == 0) + break; + if (i >= TIMO_SEND_OP) { /* Init timed out. */ printf ("card_init: SEND_OP timed out, reply = %d\n", reply); - return 0; - } - } + return 0; + } + } if (sd_timo_send_op < i) sd_timo_send_op = i; /* If SD2 read OCR register to check for SDHC card. */ - if (sd_type[unit] == 2) + if (sd_type[unit] == 2) { spi_select(sd_fd[unit]); reply = card_cmd(unit, CMD_READ_OCR, 0); - if (reply != 0) + if (reply != 0) { sd_deselect(sd_fd[unit]); printf ("sd%d: READ_OCR failed, reply=%02x\n", unit, reply); @@ -291,7 +291,7 @@ int card_init(int unit) response[2] = spi_transfer(sd_fd[unit],0xFF); response[3] = spi_transfer(sd_fd[unit],0xFF); sd_deselect(sd_fd[unit]); - if ((response[0] & 0xC0) == 0xC0) + if ((response[0] & 0xC0) == 0xC0) { sd_type[unit] = 3; } @@ -303,7 +303,7 @@ int card_init(int unit) if(unit == 1) spi_brg(sd_fd[unit],SD1_MHZ * 1000); #endif - return 1; + return 1; } /* @@ -312,52 +312,52 @@ int card_init(int unit) */ int sdsize(int unit) { - unsigned char csd [16]; - unsigned csize, n; - int reply, i; - int nsectors; + unsigned char csd [16]; + unsigned csize, n; + int reply, i; + int nsectors; - spi_select(sd_fd[unit]); - reply = card_cmd(unit,CMD_SEND_CSD, 0); - if (reply != 0) + spi_select(sd_fd[unit]); + reply = card_cmd(unit,CMD_SEND_CSD, 0); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); - return 0; - } - /* Wait for a response. */ - for (i=0; ; i++) + /* Command rejected. */ + sd_deselect(sd_fd[unit]); + return 0; + } + /* Wait for a response. */ + for (i=0; ; i++) { - reply = spi_transfer(sd_fd[unit],0xFF); - if (reply == DATA_START_BLOCK) - break; - if (i >= TIMO_SEND_CSD) + reply = spi_transfer(sd_fd[unit],0xFF); + if (reply == DATA_START_BLOCK) + break; + if (i >= TIMO_SEND_CSD) { - /* Command timed out. */ - sd_deselect(sd_fd[unit]); - printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n", + /* Command timed out. */ + sd_deselect(sd_fd[unit]); + printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n", unit, reply); - return 0; - } - } + return 0; + } + } if (sd_timo_send_csd < i) sd_timo_send_csd = i; - /* Read data. */ - for (i=0; i> 6) + switch (csd[0] >> 6) { case 1: /* SDC ver 2.00 */ csize = csd[9] + (csd[8] << 8) + 1; @@ -370,8 +370,8 @@ int sdsize(int unit) break; default: /* Unknown version. */ return 0; - } - return nsectors>>1; + } + return nsectors>>1; } /* @@ -380,44 +380,44 @@ int sdsize(int unit) */ int card_read(int unit, unsigned int offset, char *data, unsigned int bcount) { - int reply, i; + int reply, i; - /* Send read-multiple command. */ - spi_select(sd_fd[unit]); - if (sd_type[unit] != 3) offset <<= 9; - reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1); - if (reply != 0) + /* Send read-multiple command. */ + spi_select(sd_fd[unit]); + if (sd_type[unit] != 3) offset <<= 9; + reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1); + if (reply != 0) { - /* Command rejected. */ + /* Command rejected. */ printf ("sd%d: card_read: bad READ_MULTIPLE reply = %d, offset = %08x\n", unit, reply, offset<<1); - sd_deselect(sd_fd[unit]); - return 0; - } + sd_deselect(sd_fd[unit]); + return 0; + } again: - /* Wait for a response. */ - for (i=0; ; i++) + /* Wait for a response. */ + for (i=0; ; i++) { int x = spl0(); - reply = spi_transfer(sd_fd[unit],0xFF); - splx(x); - if (reply == DATA_START_BLOCK) - break; - if (i >= TIMO_READ) + reply = spi_transfer(sd_fd[unit],0xFF); + splx(x); + if (reply == DATA_START_BLOCK) + break; + if (i >= TIMO_READ) { - /* Command timed out. */ + /* Command timed out. */ printf ("sd%d: card_read: READ_MULTIPLE timed out, reply = %d\n", unit, reply); - sd_deselect(sd_fd[unit]); - return 0; - } - } + sd_deselect(sd_fd[unit]); + return 0; + } + } if (sd_timo_read < i) sd_timo_read = i; - /* Read data. */ - if (bcount >= SECTSIZE) + /* Read data. */ + if (bcount >= SECTSIZE) { spi_bulk_read_32_be(sd_fd[unit],SECTSIZE,data); data += SECTSIZE; @@ -427,11 +427,11 @@ again: for (i=bcount; i SECTSIZE) + if (bcount > SECTSIZE) { /* Next sector. */ bcount -= SECTSIZE; @@ -439,9 +439,9 @@ again: } /* Stop a read-multiple sequence. */ - card_cmd(unit, CMD_STOP, 0); - sd_deselect(sd_fd[unit]); - return 1; + card_cmd(unit, CMD_STOP, 0); + sd_deselect(sd_fd[unit]); + return 1; } /* @@ -451,40 +451,40 @@ again: int card_write (int unit, unsigned offset, char *data, unsigned bcount) { - unsigned reply, i; + unsigned reply, i; - /* Send pre-erase count. */ - spi_select(sd_fd[unit]); + /* Send pre-erase count. */ + spi_select(sd_fd[unit]); card_cmd(unit, CMD_APP, 0); - reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE); - if (reply != 0) + reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); + /* Command rejected. */ + sd_deselect(sd_fd[unit]); printf("sd%d: card_write: bad SET_WBECNT reply = %02x, count = %u\n", unit, reply, (bcount + SECTSIZE - 1) / SECTSIZE); - return 0; - } + return 0; + } - /* Send write-multiple command. */ - if (sd_type[unit] != 3) offset <<= 9; - reply = card_cmd(unit, CMD_WRITE_MULTIPLE, offset<<1); - if (reply != 0) + /* Send write-multiple command. */ + if (sd_type[unit] != 3) offset <<= 9; + reply = card_cmd(unit, CMD_WRITE_MULTIPLE, offset<<1); + if (reply != 0) { - /* Command rejected. */ - sd_deselect(sd_fd[unit]); + /* Command rejected. */ + sd_deselect(sd_fd[unit]); printf("sd%d: card_write: bad WRITE_MULTIPLE reply = %02x\n", unit, reply); - return 0; - } - sd_deselect(sd_fd[unit]); + return 0; + } + sd_deselect(sd_fd[unit]); again: /* Select, wait while busy. */ - spi_select(sd_fd[unit]); + spi_select(sd_fd[unit]); spi_wait_ready(unit, TIMO_WAIT_WDATA, &sd_timo_wait_wdata); - /* Send data. */ - spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN); - if (bcount >= SECTSIZE) + /* Send data. */ + spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN); + if (bcount >= SECTSIZE) { spi_bulk_write_32_be(sd_fd[unit],SECTSIZE,data); data += SECTSIZE; @@ -494,27 +494,27 @@ again: for (i=bcount; i SECTSIZE) + if (bcount > SECTSIZE) { /* Next sector. */ bcount -= SECTSIZE; @@ -522,18 +522,18 @@ again: } /* Stop a write-multiple sequence. */ - spi_select(sd_fd[unit]); + spi_select(sd_fd[unit]); spi_wait_ready(unit, TIMO_WAIT_WSTOP, &sd_timo_wait_wstop); - spi_transfer(sd_fd[unit],STOP_TRAN_TOKEN); + spi_transfer(sd_fd[unit],STOP_TRAN_TOKEN); spi_wait_ready(unit, TIMO_WAIT_WIDLE, &sd_timo_wait_widle); - sd_deselect(sd_fd[unit]); - return 1; + sd_deselect(sd_fd[unit]); + return 1; } void sd_preinit (int unit) { - if (unit >= NSD) - return; + if (unit >= NSD) + return; int fd = -1; if(unit==0) @@ -575,7 +575,7 @@ void sd_preinit (int unit) int sdinit (int unit, int flag) { - unsigned nsectors; + unsigned nsectors; /* Detect a card. */ #ifdef SD0_ENA_PORT @@ -596,12 +596,12 @@ int sdinit (int unit, int flag) } #endif - if (!card_init(unit)) + if (!card_init(unit)) { printf ("sd%d: no SD/MMC card detected\n", unit); return ENODEV; } - if ((nsectors=sdsize(unit))==0) + if ((nsectors=sdsize(unit))==0) { printf ("sd%d: cannot get card size\n", unit); return ENODEV; @@ -614,8 +614,8 @@ int sdinit (int unit, int flag) nsectors, spi_get_brg(sd_fd[unit]) / 1000); } - DEBUG("sd%d: init done\n",unit); - return 0; + DEBUG("sd%d: init done\n",unit); + return 0; } int sddeinit(int unit) @@ -642,6 +642,6 @@ int sddeinit(int unit) int sdopen(int unit, int flags, int mode) { - DEBUG("sd%d: open\n",unit); - return 0; + DEBUG("sd%d: open\n",unit); + return 0; } diff --git a/tools/virtualmips/dev_sdcard.c b/tools/virtualmips/dev_sdcard.c index 478cbac..82b8f9b 100644 --- a/tools/virtualmips/dev_sdcard.c +++ b/tools/virtualmips/dev_sdcard.c @@ -33,6 +33,7 @@ #define CMD_GO_IDLE (0x40+0) /* CMD0 */ #define CMD_SEND_OP_SDC (0x40+41) /* ACMD41 (SDC) */ #define CMD_SET_BLEN (0x40+16) +#define CMD_SEND_IF_COND (0x40+8) #define CMD_SEND_CSD (0x40+9) #define CMD_STOP (0x40+12) #define CMD_READ_SINGLE (0x40+17) @@ -330,6 +331,12 @@ unsigned dev_sdcard_io (cpu_mips_t *cpu, unsigned data) d->read_multiple = 0; reply = 0; break; + case CMD_SEND_IF_COND: /* Stop read-multiple sequence */ + if (d->count > 1) + break; + d->read_multiple = 0; + reply = 4; /* Unknown command */ + break; case 0: /* Reply */ if (d->count <= d->limit) { reply = d->buf [d->count++]; From 0b3148640240af52e21f915ebfb1d62f7f04f13c Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Wed, 21 May 2014 12:26:24 -0700 Subject: [PATCH 06/40] Added loadmax target to kernel Makefile. Use "make loadmax" in sys/pic32/max32 directory to upload the kernel image to chipKIT Max32 board. --- sys/pic32/kernel-post.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/pic32/kernel-post.mk b/sys/pic32/kernel-post.mk index 5f161c8..8628c0d 100644 --- a/sys/pic32/kernel-post.mk +++ b/sys/pic32/kernel-post.mk @@ -67,6 +67,9 @@ bl_devcfg.o: $(BUILDPATH)/devcfg.c load: unix.hex pic32prog $(BLREBOOT) unix.hex +loadmax: unix.hex + $(PROGTOOL) -U flash:w:unix.hex:i + loadboot: bootloader.hex pic32prog $(BLREBOOT) bootloader.hex From 66ffc30ccd36b4858e7ba571571fc4109284b1d5 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 23 May 2014 11:33:58 -0700 Subject: [PATCH 07/40] Kernel makefiles updated. --- sys/pic32/32mxsdram-uart/Makefile | 2 +- sys/pic32/Makefile | 7 ++-- sys/pic32/baremetal/Makefile | 2 +- sys/pic32/cfg/kernel.dev | 2 +- sys/pic32/dip/Makefile | 2 +- sys/pic32/duinomite-e-uart/DUINOMITE-E-UART | 2 +- sys/pic32/duinomite-e-uart/Makefile | 42 +++++++++++++++++-- sys/pic32/duinomite-e/DUINOMITE-E | 3 +- sys/pic32/duinomite-e/Makefile | 42 +++++++++++++++++-- sys/pic32/duinomite-uart/Makefile | 2 +- sys/pic32/duinomite/Makefile | 2 +- sys/pic32/explorer16/Makefile | 2 +- sys/pic32/fubarino/Makefile | 2 +- sys/pic32/max32-eth/Makefile | 2 +- sys/pic32/max32/Makefile | 2 +- .../{MAXCOLOR => MAXIMITE-COLOR} | 0 sys/pic32/maximite-color/Makefile | 7 +++- sys/pic32/maximite/Makefile | 2 +- sys/pic32/meb/Makefile | 2 +- sys/pic32/mmb-mx7/Makefile | 2 +- sys/pic32/pinguino-micro/Makefile | 2 +- sys/pic32/starter-kit/Makefile | 2 +- sys/pic32/{_startup.S => startup.S} | 0 sys/pic32/ubw32-uart-sdram/Makefile | 2 +- sys/pic32/ubw32-uart/Makefile | 2 +- sys/pic32/ubw32/Makefile | 2 +- 26 files changed, 107 insertions(+), 32 deletions(-) rename sys/pic32/maximite-color/{MAXCOLOR => MAXIMITE-COLOR} (100%) rename sys/pic32/{_startup.S => startup.S} (100%) diff --git a/sys/pic32/32mxsdram-uart/Makefile b/sys/pic32/32mxsdram-uart/Makefile index 4edfea6..1a220e5 100644 --- a/sys/pic32/32mxsdram-uart/Makefile +++ b/sys/pic32/32mxsdram-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/Makefile b/sys/pic32/Makefile index d06a76f..193371e 100644 --- a/sys/pic32/Makefile +++ b/sys/pic32/Makefile @@ -4,8 +4,7 @@ SUBDIR = baremetal dip duinomite duinomite-uart duinomite-e \ duinomite-e-uart explorer16 max32 max32-eth maximite \ meb pinguino-micro starter-kit ubw32 ubw32-uart \ - ubw32-uart-sdram baremetal fubarino fubarino-uart \ - fubarino-uart-sramc mmb-mx7 maximite-color \ + ubw32-uart-sdram baremetal fubarino mmb-mx7 maximite-color \ 32mxsdram-uart default: @@ -20,4 +19,6 @@ clean: find .. -name \*~ | xargs rm -f reconfig: - -for i in $(SUBDIR); do echo $$i; I=`echo $$i | awk '{print toupper($$0)}'`; (cd $$i; ../../../tools/configsys/config $$I); done + -for i in $(SUBDIR); do echo $$i; \ + I=`echo $$i | awk '{print toupper($$0)}'`; \ + (cd $$i; ../../../tools/configsys/config $$I); done diff --git a/sys/pic32/baremetal/Makefile b/sys/pic32/baremetal/Makefile index ba3e606..1351297 100644 --- a/sys/pic32/baremetal/Makefile +++ b/sys/pic32/baremetal/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/cfg/kernel.dev b/sys/pic32/cfg/kernel.dev index e18f2b8..9888aa2 100644 --- a/sys/pic32/cfg/kernel.dev +++ b/sys/pic32/cfg/kernel.dev @@ -4,7 +4,7 @@ always define EXEC_AOUT define EXEC_ELF define EXEC_SCRIPT - file _startup.o + file startup.o file clock.o file devsw.o file sysctl.o diff --git a/sys/pic32/dip/Makefile b/sys/pic32/dip/Makefile index 2a83cab..3c80da9 100644 --- a/sys/pic32/dip/Makefile +++ b/sys/pic32/dip/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=6 diff --git a/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART b/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART index 525a055..f68fb27 100644 --- a/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART +++ b/sys/pic32/duinomite-e-uart/DUINOMITE-E-UART @@ -10,7 +10,7 @@ linker bootloader-maximite device kernel cpu_khz=80000 bus_khz=40000 led=B15 -device console port=UART5 +device console device=tty5 device uart5 baud=115200 power=G13 device rdisk led=C1 diff --git a/sys/pic32/duinomite-e-uart/Makefile b/sys/pic32/duinomite-e-uart/Makefile index b23e0d0..3906a5e 100644 --- a/sys/pic32/duinomite-e-uart/Makefile +++ b/sys/pic32/duinomite-e-uart/Makefile @@ -6,11 +6,44 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_glob.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_log.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_conf.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = +DEFS += -DBUS_DIV=1 DEFS += -DBUS_KHZ=40000 -DEFS += -DCONSOLE_UART5=YES +DEFS += -DCONSOLE_DEVICE=tty5 +DEFS += -DCPU_IDIV=2 DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DGPIO_ENABLED=YES DEFS += -DKERNEL DEFS += -DLED_DISK_PIN=1 @@ -30,6 +63,9 @@ DEFS += -DUART5_ENA_PORT=TRISG DEFS += -DUCB_METER -LDSCRIPT = ../../../tools/configsys/../../sys/pic32/lds/bootloader-maximite.ld +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maximite.ld + +CONFIG = DUINOMITE-E-UART +CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/duinomite-e/DUINOMITE-E b/sys/pic32/duinomite-e/DUINOMITE-E index ed4577e..c69448c 100644 --- a/sys/pic32/duinomite-e/DUINOMITE-E +++ b/sys/pic32/duinomite-e/DUINOMITE-E @@ -11,11 +11,10 @@ linker bootloader-maximite device kernel cpu_khz=80000 bus_khz=40000 led=B15 -device console port=USB +device console device=ttyUSB0 device uartusb device rdisk led=C1 device sd0 port=3 cs=G12 power=G13 device gpio - diff --git a/sys/pic32/duinomite-e/Makefile b/sys/pic32/duinomite-e/Makefile index aab6603..edb68f2 100644 --- a/sys/pic32/duinomite-e/Makefile +++ b/sys/pic32/duinomite-e/Makefile @@ -6,11 +6,44 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_glob.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_log.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_conf.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = +DEFS += -DBUS_DIV=1 DEFS += -DBUS_KHZ=40000 -DEFS += -DCONSOLE_USB=YES +DEFS += -DCONSOLE_DEVICE=ttyUSB0 +DEFS += -DCPU_IDIV=2 DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DGPIO_ENABLED=YES DEFS += -DKERNEL DEFS += -DLED_DISK_PIN=1 @@ -29,6 +62,9 @@ DEFS += -DUSB_MAX_EP_NUMBER=3 DEFS += -DUSB_NUM_STRING_DESCRIPTORS=3 -LDSCRIPT = ../../../tools/configsys/../../sys/pic32/lds/bootloader-maximite.ld +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maximite.ld + +CONFIG = DUINOMITE-E +CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/duinomite-uart/Makefile b/sys/pic32/duinomite-uart/Makefile index 2a94d01..e8c795e 100644 --- a/sys/pic32/duinomite-uart/Makefile +++ b/sys/pic32/duinomite-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/duinomite/Makefile b/sys/pic32/duinomite/Makefile index a62bfe2..8fba7b2 100644 --- a/sys/pic32/duinomite/Makefile +++ b/sys/pic32/duinomite/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/explorer16/Makefile b/sys/pic32/explorer16/Makefile index a4a9fd7..af3189f 100644 --- a/sys/pic32/explorer16/Makefile +++ b/sys/pic32/explorer16/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/fubarino/Makefile b/sys/pic32/fubarino/Makefile index 5f852c2..f9ace21 100644 --- a/sys/pic32/fubarino/Makefile +++ b/sys/pic32/fubarino/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o glcd.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o glcd.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o oc.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/max32-eth/Makefile b/sys/pic32/max32-eth/Makefile index 12601e9..81652c2 100644 --- a/sys/pic32/max32-eth/Makefile +++ b/sys/pic32/max32-eth/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/max32/Makefile b/sys/pic32/max32/Makefile index 5a647f2..43b9bd3 100644 --- a/sys/pic32/max32/Makefile +++ b/sys/pic32/max32/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/maximite-color/MAXCOLOR b/sys/pic32/maximite-color/MAXIMITE-COLOR similarity index 100% rename from sys/pic32/maximite-color/MAXCOLOR rename to sys/pic32/maximite-color/MAXIMITE-COLOR diff --git a/sys/pic32/maximite-color/Makefile b/sys/pic32/maximite-color/Makefile index 2629593..856905a 100644 --- a/sys/pic32/maximite-color/Makefile +++ b/sys/pic32/maximite-color/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=13 @@ -45,6 +45,9 @@ DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO DEFS += -DDC3_USERID=0xffff DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT DEFS += -DFLASH_USER=0x1d005000 DEFS += -DGPIO_ENABLED=YES DEFS += -DHID_FEATURE_REPORT_BYTES=2 @@ -72,7 +75,7 @@ DEFS += -DUSB_NUM_STRING_DESCRIPTORS=3 LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-maxcolor.ld -CONFIG = MAXCOLOR +CONFIG = MAXIMITE-COLOR CONFIGPATH = ../../../tools/configsys include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/maximite/Makefile b/sys/pic32/maximite/Makefile index 248067b..95dd29a 100644 --- a/sys/pic32/maximite/Makefile +++ b/sys/pic32/maximite/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=13 diff --git a/sys/pic32/meb/Makefile b/sys/pic32/meb/Makefile index ba53acd..7a022df 100644 --- a/sys/pic32/meb/Makefile +++ b/sys/pic32/meb/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devcfg.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DBUS_DIV=1 diff --git a/sys/pic32/mmb-mx7/Makefile b/sys/pic32/mmb-mx7/Makefile index 9eae304..6566e10 100644 --- a/sys/pic32/mmb-mx7/Makefile +++ b/sys/pic32/mmb-mx7/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/pinguino-micro/Makefile b/sys/pic32/pinguino-micro/Makefile index 2b3706f..633a7a7 100644 --- a/sys/pic32/pinguino-micro/Makefile +++ b/sys/pic32/pinguino-micro/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/starter-kit/Makefile b/sys/pic32/starter-kit/Makefile index efba415..7d8d018 100644 --- a/sys/pic32/starter-kit/Makefile +++ b/sys/pic32/starter-kit/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DADC_ENABLED=YES diff --git a/sys/pic32/_startup.S b/sys/pic32/startup.S similarity index 100% rename from sys/pic32/_startup.S rename to sys/pic32/startup.S diff --git a/sys/pic32/ubw32-uart-sdram/Makefile b/sys/pic32/ubw32-uart-sdram/Makefile index 84b52ed..8e73a02 100644 --- a/sys/pic32/ubw32-uart-sdram/Makefile +++ b/sys/pic32/ubw32-uart-sdram/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_sdramp.o rdisk.o sdram.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 diff --git a/sys/pic32/ubw32-uart/Makefile b/sys/pic32/ubw32-uart/Makefile index 8ff0aec..a0f2b45 100644 --- a/sys/pic32/ubw32-uart/Makefile +++ b/sys/pic32/ubw32-uart/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 diff --git a/sys/pic32/ubw32/Makefile b/sys/pic32/ubw32/Makefile index 39699a2..64f97a9 100644 --- a/sys/pic32/ubw32/Makefile +++ b/sys/pic32/ubw32/Makefile @@ -6,7 +6,7 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += _startup.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o usb_device.o usb_function_cdc.o usb_uart.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = bootloader DEFS += -DBL_BUTTON_PIN=7 From b3abe580bda2909c04ce6fba28829e1f5577bdbe Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 May 2014 19:37:02 -0700 Subject: [PATCH 08/40] Added emg editor from github.com/ibara/emg. --- share/.gitignore | 1 + src/cmd/Makefile | 4 +- src/cmd/emg/.gitignore | 1 + src/cmd/emg/ChangeLog | 41 ++ src/cmd/emg/Makefile | 49 ++ src/cmd/emg/README | 44 ++ src/cmd/emg/README-ERSATZ | 39 ++ src/cmd/emg/basic.c | 266 ++++++++++ src/cmd/emg/buffer.c | 494 ++++++++++++++++++ src/cmd/emg/display.c | 1015 +++++++++++++++++++++++++++++++++++++ src/cmd/emg/ebind.h | 75 +++ src/cmd/emg/edef.h | 78 +++ src/cmd/emg/efunc.h | 70 +++ src/cmd/emg/emg.1 | 58 +++ src/cmd/emg/emg.keys | 147 ++++++ src/cmd/emg/estruct.h | 162 ++++++ src/cmd/emg/file.c | 465 +++++++++++++++++ src/cmd/emg/fileio.c | 121 +++++ src/cmd/emg/line.c | 507 ++++++++++++++++++ src/cmd/emg/main.c | 465 +++++++++++++++++ src/cmd/emg/random.c | 290 +++++++++++ src/cmd/emg/region.c | 142 ++++++ src/cmd/emg/search.c | 535 +++++++++++++++++++ src/cmd/emg/tcap.c | 144 ++++++ src/cmd/emg/ttyio.c | 163 ++++++ src/cmd/emg/window.c | 336 ++++++++++++ src/cmd/emg/word.c | 284 +++++++++++ 27 files changed, 5994 insertions(+), 2 deletions(-) create mode 100644 src/cmd/emg/.gitignore create mode 100644 src/cmd/emg/ChangeLog create mode 100644 src/cmd/emg/Makefile create mode 100644 src/cmd/emg/README create mode 100644 src/cmd/emg/README-ERSATZ create mode 100644 src/cmd/emg/basic.c create mode 100644 src/cmd/emg/buffer.c create mode 100644 src/cmd/emg/display.c create mode 100644 src/cmd/emg/ebind.h create mode 100644 src/cmd/emg/edef.h create mode 100644 src/cmd/emg/efunc.h create mode 100644 src/cmd/emg/emg.1 create mode 100644 src/cmd/emg/emg.keys create mode 100644 src/cmd/emg/estruct.h create mode 100644 src/cmd/emg/file.c create mode 100644 src/cmd/emg/fileio.c create mode 100644 src/cmd/emg/line.c create mode 100644 src/cmd/emg/main.c create mode 100644 src/cmd/emg/random.c create mode 100644 src/cmd/emg/region.c create mode 100644 src/cmd/emg/search.c create mode 100644 src/cmd/emg/tcap.c create mode 100644 src/cmd/emg/ttyio.c create mode 100644 src/cmd/emg/window.c create mode 100644 src/cmd/emg/word.c diff --git a/share/.gitignore b/share/.gitignore index 0d1783a..6847704 100644 --- a/share/.gitignore +++ b/share/.gitignore @@ -1,3 +1,4 @@ re.help misc unixbench +emg.keys diff --git a/src/cmd/Makefile b/src/cmd/Makefile index f3fdf44..f5c7ae2 100644 --- a/src/cmd/Makefile +++ b/src/cmd/Makefile @@ -11,8 +11,8 @@ CFLAGS += -Werror # Programs that live in subdirectories, and have makefiles of their own. # /bin SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \ - cpp dc diff env fdisk find forth fstat glcdtest hostname \ - id la lcc lcpp ld ls login make man med \ + cpp dc diff emg env fdisk find forth fstat glcdtest \ + hostname id la lcc lcpp ld ls login make man med \ more nm passwd picoc portio printf pwm \ rdprof ranlib re renice retroforth scm setty sl \ sed sh smallc smlrc stty sysctl test uname wiznet xargs \ diff --git a/src/cmd/emg/.gitignore b/src/cmd/emg/.gitignore new file mode 100644 index 0000000..19a9d31 --- /dev/null +++ b/src/cmd/emg/.gitignore @@ -0,0 +1 @@ +emg diff --git a/src/cmd/emg/ChangeLog b/src/cmd/emg/ChangeLog new file mode 100644 index 0000000..9c41af6 --- /dev/null +++ b/src/cmd/emg/ChangeLog @@ -0,0 +1,41 @@ +ChangeLog +========= + +March 16, 2014 : emg 1.5 +------------------------ +Add line number to the mode line. +Implement prompted go to line function. +Remove lesser used expensive movement functions. +Documentation tweaks to reflect above changes. + +March 9, 2014 : emg 1.4 +----------------------- +Huge whitespace cleanup. +Make the window creation code mode consistent. +Small documentation fix. + +March 8, 2014 : emg 1.3 +----------------------- +Remove all OpenBSD support. emg is now for RetroBSD only. +Remove tmux alternative keybindings. +Revert Listbuffer command back to CTRL-x CTRL-b. + +December 2, 2013 : emg 1.2 +-------------------------- +Alternate keybindings for RetroBSD users using flow control terminal emulators. +Alternate keybindings for tmux users who are using the default control command. + +October 24, 2013 : emg 1.1 +-------------------------- +Listbuffer command is now CTRL-x l (originally CTRL-x CTRL-b). + This is because the default command keybinding of tmux is CTRL-b. +Search is now executed with instead of . + felt awkward, plus I don't search for newlines. +Lots of code cleanups (ttyio.c). + Removal of unused #if blocks. + Use panic() everywhere. + Fix all warnings from gcc -Wall. + +October 19, 2013 : emg 1.0 +-------------------------- +Initial version of emg. Current targets are OpenBSD and RetroBSD. diff --git a/src/cmd/emg/Makefile b/src/cmd/emg/Makefile new file mode 100644 index 0000000..ff0b3cc --- /dev/null +++ b/src/cmd/emg/Makefile @@ -0,0 +1,49 @@ +# emg Makefile +# for RetroBSD + +TOPSRC = $(shell cd ../../..; pwd) +include $(TOPSRC)/target.mk + +# Some basic CFLAGS. +CFLAGS = -Os -Wall -Werror + +# With the extra LDFLAGS, save some bytes. +CFLAGS += -ffunction-sections -fdata-sections + +# This reduces code size to 46K. +CFLAGS += -mips16 + +# Set the screen size. +# Will default to FORCE_COLS=80 and FORCE_ROWS=24 +# if not set here. +CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24 + +# with CFLAGS+= -ffunction-sections -fdatasections +LDFLAGS += -Wl,--gc-sections + +LIBS = -ltermcap -lc + +MAN = emg.0 +MANSRC = emg.1 + +OBJS = basic.o buffer.o display.o file.o fileio.o line.o main.o \ + random.o region.o search.o tcap.o ttyio.o window.o word.o + +all: emg ${MAN} + +emg: ${OBJS} + ${CC} ${LDFLAGS} -o emg.elf ${OBJS} ${LIBS} + ${OBJDUMP} -S emg.elf > emg.dis + ${SIZE} emg.elf + ${ELF2AOUT} emg.elf $@ && rm emg.elf + +${MAN}: ${MANSRC} + ${MANROFF} ${MANSRC} > ${MAN} + +install: all + install emg ${DESTDIR}/bin/emg + cp ${MAN} ${DESTDIR}/share/man/cat1/ + cp -p emg.keys ${DESTDIR}/share/emg.keys + +clean: + rm -f *.o *~ *.core *.bak *.dis emg ${MAN} diff --git a/src/cmd/emg/README b/src/cmd/emg/README new file mode 100644 index 0000000..1bde8f3 --- /dev/null +++ b/src/cmd/emg/README @@ -0,0 +1,44 @@ +emg +=== + +emg, or Ersatz Mg, is a very tiny Emacs-like text editor created by +combining elements of Ersatz Emacs and Mg (both the mg1a release and the +current OpenBSD-maintained version). + +The goal of this editor is to have something Emacs like for RetroBSD +(a release of 2.11BSD for PIC32 microcontrollers). After noticing that the +vi clone RetroBSD is using, VIrus, is GPL-licensed, I decided to provide +a better-licensed editor. I also decided that, as a vi user myself, it would +be easier to create an Emacs clone. Like you, I'm also unsure as to how that +conclusion was reached. + +I had initially tried to port Mg to RetroBSD but it was simply too large. +Ersatz Emacs does not build on RetroBSD, as RetroBSD is missing some functions +that Ersatz Emacs requires. It made sense to try to take from each and create +an editor that would work. + +In a way, emg has a double meaning: not only is it a combination of +the two programs that comprise it, it is also a substitute Mg after my initial +port failed. + +I have cleaned up some code where necessary; emg builds without errors on +RetroBSD. + +Patches are also very welcome. I ask that you keep in mind the resource +constraints of RetroBSD: everything must fit in 96K RAM. But of course, +smaller is better. + +I've left Chris Baird's Ersatz Emacs README here so others can better +appreciate the history of this software. + +As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. + +Versions of emg up to and including 1.2 also supported OpenBSD; OpenBSD +has since dropped the older headers, such as sgtty.h and it is not worth +reimplementing these for OpenBSD, since OpenBSD maintains Mg. + +Tarballs can be found here: +http://devio.us/~bcallah/emg/ + +Github repo, for patches: +https://github.com/ibara/emg diff --git a/src/cmd/emg/README-ERSATZ b/src/cmd/emg/README-ERSATZ new file mode 100644 index 0000000..381b816 --- /dev/null +++ b/src/cmd/emg/README-ERSATZ @@ -0,0 +1,39 @@ +This shar file contains the source to a microemacs-derived text editor +that I have been personally hacking on for over a decade. + +Originally this was MicroEMACS 3.6 as released to mod.sources and the +Public Domain by Daniel Lawrence in 1986, and was itself based on the +work of Steve Wilhite and George Jones to MicroEMACS 2.0 (then also +public domain) by Dave Conroy. I would like to reiterate Lawrence's +thanks to them for writing such nice, well structured and documented +code. + +"Ersatz-Emacs", as I call it today, is the above text editor throughly +cleansed of routines and features that I personally never use. It is +also an editor MINIX-creator Andy Tanenbaum could describe as "fitting +inside a student's brain" (namely, mine). + +This source code should compile cleanly on any "modern" UN*X system +with a termcap/curses library. This release has been tested with +NetBSD and various Linux systems, although in the past when it was +still mostly MicroEMACS, proto-Ersatz-Emacs was an editor of choice on +SunOS, Solaris, Xenix, Minix/i386, and AIX. Supporting these and +similar systems should not be difficult. + +I encourage people to personalise this very simple editor to their own +requirements. Please send any useful bug reports and fixes back to me, +but I'm not really interested in incorporating new features unless it +simplifies the program further. Feel free to do a code-fork and +distribute your own perfect text editor. + +The title "Ersatz" comes from the category Richard Stallman uses in +MIT AI Memo 519a to describe those editors that are a surface-deep +imitation (key bindings) of "real" ITS Emacs. If you are familiar with +any Emacs-variant editor, you should have few problems with Ersatz. + +All source code of this program is in the Public Domain. I am a rabid +Stallmanite weenie, but it would be improper to publish this under a +different licence than it was given to me with. + +-- +Chris Baird,, diff --git a/src/cmd/emg/basic.c b/src/cmd/emg/basic.c new file mode 100644 index 0000000..ca7d30f --- /dev/null +++ b/src/cmd/emg/basic.c @@ -0,0 +1,266 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file move the cursor around on the screen. They + * compute a new value for the cursor, then adjust ".". The display code + * always updates the cursor location, so only moves between lines, or + * functions that adjust the top line in the window and invalidate the + * framing, are hard. + */ + +#include /* atoi(3), ugh */ +#include "estruct.h" +#include "edef.h" + +extern int getccol(int bflg); +extern int inword(); +extern void mlwrite(); +extern int mlreplyt(); + +int forwchar(int f, int n); +int backchar(int f, int n); +int forwline(int f, int n); +int backline(int f, int n); + +/* + * This routine, given a pointer to a LINE, and the current cursor goal + * column, return the best choice for the offset. The offset is returned. + * Used by "C-N" and "C-P". + */ +long getgoal(LINE *dlp) +{ + int col = 0; + int dbo = 0; + int newcol, c; + + while (dbo != llength(dlp)) + { + c = lgetc(dlp, dbo); + newcol = col; + if (c == '\t') + newcol |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++newcol; + ++newcol; + if (newcol > curgoal) + break; + col = newcol; + ++dbo; + } + return (dbo); +} + +/* + * Move the cursor to the + * beginning of the current line. + * Trivial. + */ +/* ARGSUSED0 */ +int gotobol(int f, int n) +{ + curwp->w_doto = 0; + return (TRUE); +} + +/* + * Move the cursor to the end of the current line. Trivial. No errors. + */ +/* ARGSUSED0 */ +int gotoeol(int f, int n) +{ + curwp->w_doto = llength(curwp->w_dotp); + return (TRUE); +} + +/* + * Move the cursor backwards by "n" characters. If "n" is less than zero call + * "forwchar" to actually do the move. Otherwise compute the new cursor + * location. Error if you try and move out of the buffer. Set the flag if the + * line pointer for dot changes. + */ +int backchar(int f, int n) +{ + LINE *lp; + + if (n < 0) + return (forwchar(f, -n)); + while (n--) + { + if (curwp->w_doto == 0) + { + if ((lp = lback(curwp->w_dotp)) == curbp->b_linep) + return (FALSE); + curwp->w_dotp = lp; + curwp->w_doto = llength(lp); + curwp->w_flag |= WFMOVE; + curwp->w_dotline--; + } + else + curwp->w_doto--; + } + return (TRUE); +} + +/* + * Move the cursor forwards by "n" characters. If "n" is less than zero call + * "backchar" to actually do the move. Otherwise compute the new cursor + * location, and move ".". Error if you try and move off the end of the + * buffer. Set the flag if the line pointer for dot changes. + */ +int forwchar(int f, int n) +{ + if (n < 0) + return (backchar(f, -n)); + while (n--) + { + if (curwp->w_doto == llength(curwp->w_dotp)) + { + if (curwp->w_dotp == curbp->b_linep) + return (FALSE); + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + curwp->w_dotline++; + } + else + curwp->w_doto++; + } + return (TRUE); +} + +/* + * move to a particular line. argument (n) must be a positive integer for this + * to actually do anything + */ +int gotoline(int f, int n) +{ + if ((n < 1) || (n > curwp->w_bufp->b_lines)) /* if a bogus argument...then leave */ + return (FALSE); /* but we should never get here */ + + /* first, we go to the start of the buffer */ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_dotline = 0; /* and reset the line number */ + return (forwline(f, n - 1)); +} + +/* + * Prompt for which line number we want to go to, then execute gotoline() + * with that number as its argument. + * + * Make sure the bounds are within the file. + * + * Bound to M-G + */ +int setline(int f, int n) +{ + char setl[6]; + int l; + + (void)mlreplyt("Go to line: ", setl, 6, 10); + l = atoi(setl); /* XXX: This sucks! */ + + if (l < 1) + l = 1; + else if (l > curwp->w_bufp->b_lines) + l = curwp->w_bufp->b_lines; + + gotoline(f, l); + return (TRUE); +} + +/* + * Goto the beginning of the buffer. Massive adjustment of dot. This is + * considered to be hard motion; it really isn't if the original value of dot + * is the same as the new value of dot. Normally bound to "M-<". + */ +/* ARGSUSED0 */ +int gotobob(int f, int n) +{ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + curwp->w_dotline = 0; + return (TRUE); +} + +/* + * Move to the end of the buffer. Dot is always put at the end of the file + * (ZJ). The standard screen code does most of the hard parts of update. + * Bound to "M->". + */ +/* ARGSUSED0 */ +int gotoeob(int f, int n) +{ + curwp->w_dotp = curbp->b_linep; + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + curwp->w_dotline = curwp->w_bufp->b_lines; + return (TRUE); +} + +/* + * Move forward by full lines. If the number of lines to move is less than + * zero, call the backward line function to actually do it. The last command + * controls how the goal column is set. Bound to "C-N". No errors are possible. + */ +int forwline(int f, int n) +{ + LINE *dlp; + + if (n < 0) + return (backline(f, -n)); + if ((lastflag & CFCPCN) == 0)/* Reset goal if last */ + curgoal = getccol(FALSE); /* not C-P or C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && dlp != curbp->b_linep) + { + dlp = lforw(dlp); + curwp->w_dotline++; + } + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + +/* + * This function is like "forwline", but goes backwards. The scheme is exactly + * the same. Check for arguments that are less than zero and call your + * alternate. Figure out the new line and call "movedot" to perform the + * motion. No errors are possible. Bound to "C-P". + */ +int backline(int f, int n) +{ + LINE *dlp; + + if (n < 0) + return (forwline(f, -n)); + if ((lastflag & CFCPCN) == 0)/* Reset goal if the */ + curgoal = getccol(FALSE); /* last isn't C-P, C-N */ + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && lback(dlp) != curbp->b_linep) + { + dlp = lback(dlp); + curwp->w_dotline--; + } + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + +/* + * Set the mark in the current window to the value of "." in the window. No + * errors are possible. Bound to "M-.". + */ +/* ARGSUSED0 */ +int setmark(int f, int n) +{ + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = curwp->w_doto; + mlwrite("[Mark set]"); + return (TRUE); +} diff --git a/src/cmd/emg/buffer.c b/src/cmd/emg/buffer.c new file mode 100644 index 0000000..ac49d40 --- /dev/null +++ b/src/cmd/emg/buffer.c @@ -0,0 +1,494 @@ +/* This file is in the public domain. */ + +/* + * Buffer management. Some of the functions are internal, and some are actually + * attached to user keys. Like everyone else, they set hints for the display + * system. + */ + +#include /* free(3), malloc(3) */ +#include /* strncpy(3) */ +#include "estruct.h" +#include "edef.h" + +extern int mlreply(char *prompt, char *buf, int nbuf); +extern int readin(char fname[]); +extern void mlwrite(); +extern void mlerase(); +extern int mlyesno(char *prompt); +extern void lfree(LINE *lp); +extern WINDOW *wpopup(); +extern LINE *lalloc(); + +int swbuffer(BUFFER *bp); +int usebuffer(int f, int n); +int nextbuffer(int f, int n); +int killbuffer(int f, int n); +int zotbuf(BUFFER *bp); +int namebuffer(int f, int n); +int listbuffers(int f, int n); +int makelist(); +void itoa(char buf[], int width, int num); +int addline(char *text); +int anycb(); +BUFFER* bfind(char *bname, int cflag, int bflag); +int bclear(BUFFER *bp); + +/* + * make buffer BP current + */ +int swbuffer(BUFFER *bp) +{ + WINDOW *wp; + + if (--curbp->b_nwnd == 0) + { /* Last use. */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + curbp = bp; /* Switch. */ + if (curbp->b_active != TRUE) + { /* buffer not active yet */ + /* read it in and activate it */ + readin(curbp->b_fname); + curbp->b_dotp = lforw(curbp->b_linep); + curbp->b_doto = 0; + curbp->b_active = TRUE; + } + curwp->w_bufp = bp; + curwp->w_linep = bp->b_linep; /* For macros, ignored */ + curwp->w_flag |= WFMODE | WFFORCE | WFHARD; /* Quite nasty */ + if (bp->b_nwnd++ == 0) + { /* First use */ + curwp->w_dotp = bp->b_dotp; + curwp->w_doto = bp->b_doto; + curwp->w_markp = bp->b_markp; + curwp->w_marko = bp->b_marko; + return (TRUE); + } + wp = wheadp; /* Look for old */ + while (wp != 0) + { + if (wp != curwp && wp->w_bufp == bp) + { + curwp->w_dotp = wp->w_dotp; + curwp->w_doto = wp->w_doto; + curwp->w_markp = wp->w_markp; + curwp->w_marko = wp->w_marko; + break; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Attach a buffer to a window. The values of dot and mark come from the buffer + * if the use count is 0. Otherwise, they come from some other window. + */ +/* ARGSUSED0 */ +int usebuffer(int f, int n) +{ + BUFFER *bp; + char bufn[NBUFN]; + int s; + + if ((s = mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) + return (s); + if ((bp = bfind(bufn, TRUE, 0)) == NULL) + return (FALSE); + return (swbuffer(bp)); +} + +/* switch to the next buffer in the buffer list + */ +/* ARGSUSED0 */ +int nextbuffer(int f, int n) +{ + BUFFER *bp; + + bp = curbp->b_bufp; + /* cycle through the buffers to find an eligable one */ + while ((bp == NULL) || (bp->b_flag & BFTEMP)) + { + if (bp == NULL) + bp = bheadp; + else + bp = bp->b_bufp; + } + return (swbuffer(bp)); +} + +/* + * Dispose of a buffer, by name. Ask for the name. Look it up (don't get too + * upset if it isn't there at all!). Get quite upset if the buffer is being + * displayed. Clear the buffer (ask if the buffer has been changed). Then free + * the header line and the buffer header. Bound to "C-X K". + */ +/* ARGSUSED0 */ +int killbuffer(int f, int n) +{ + BUFFER *bp; + char bufn[NBUFN]; + int s; + + if ((s = mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) + return (s); + if ((bp = bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown */ + return (TRUE); + return (zotbuf(bp)); +} + +/* kill the buffer pointed to by bp */ +int zotbuf(BUFFER *bp) +{ + BUFFER *bp1, *bp2; + int s; + + if (bp->b_nwnd != 0) + { /* Error if on screen */ + mlwrite("Buffer is being displayed"); + return (FALSE); + } + if ((s = bclear(bp)) != TRUE) /* Blow text away */ + return (s); + free (bp->b_linep); /* Release header line */ + bp1 = 0; /* Find the header */ + bp2 = bheadp; + while (bp2 != bp) + { + bp1 = bp2; + bp2 = bp2->b_bufp; + } + bp2 = bp2->b_bufp; /* Next one in chain */ + if (bp1 == NULL) /* Unlink it */ + bheadp = bp2; + else + bp1->b_bufp = bp2; + free(bp); /* Release buffer block */ + return (TRUE); +} + +/* Rename the current buffer */ +/* ARGSUSED0 */ +int namebuffer(int f, int n) +{ + BUFFER *bp; /* pointer to scan through all buffers */ + char bufn[NBUFN]; /* buffer to hold buffer name */ + + /* prompt for and get the new buffer name */ + ask: + if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) + return (FALSE); + + /* and check for duplicates */ + bp = bheadp; + while (bp != 0) + { + if (bp != curbp) + { + /* if the names the same */ + if (strcmp(bufn, bp->b_bname) == 0) + goto ask; /* try again */ + } + bp = bp->b_bufp; /* onward */ + } + + strncpy(curbp->b_bname, bufn, NBUFN); /* copy buffer name to structure */ + curwp->w_flag |= WFMODE; /* make mode line replot */ + mlerase(); + return (TRUE); +} + +/* + * List all of the active buffers. First update the special buffer that holds + * the list. Next make sure at least 1 window is displaying the buffer list, + * splitting the screen if this is what it takes. Lastly, repaint all of the + * windows that are displaying the list. Bound to "C-X C-B". + */ +/* ARGSUSED0 */ +int listbuffers(int f, int n) +{ + WINDOW *wp; + BUFFER *bp; + int s; + + if ((s = makelist()) != TRUE) + return (s); + if (blistp->b_nwnd == 0) + { /* Not on screen yet */ + if ((wp = wpopup()) == NULL) + return (FALSE); + bp = wp->w_bufp; + if (--bp->b_nwnd == 0) + { + bp->b_dotp = wp->w_dotp; + bp->b_doto = wp->w_doto; + bp->b_markp = wp->w_markp; + bp->b_marko = wp->w_marko; + } + wp->w_bufp = blistp; + ++blistp->b_nwnd; + } + wp = wheadp; + while (wp != 0) + { + if (wp->w_bufp == blistp) + { + wp->w_linep = lforw(blistp->b_linep); + wp->w_dotp = lforw(blistp->b_linep); + wp->w_doto = 0; + wp->w_markp = 0; + wp->w_marko = 0; + wp->w_flag |= WFMODE | WFHARD; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * This routine rebuilds the text in the special secret buffer that holds the + * buffer list. It is called by the list buffers command. Return TRUE if + * everything works. Return FALSE if there is an error (if there is no + * memory). + */ +int makelist() +{ + BUFFER *bp; + LINE *lp; + char *cp1, *cp2; + char b[7], line[128]; + int nbytes, s, c; + + blistp->b_flag &= ~BFCHG; /* Don't complain! */ + if ((s = bclear(blistp)) != TRUE) /* Blow old text away */ + return (s); + strncpy (blistp->b_fname, "", 1); + if (addline("AC Size Buffer File") == FALSE || + addline("-- ------- ------ ----") == FALSE) + return (FALSE); + bp = bheadp; + + /* build line to report global mode settings */ + cp1 = &line[0]; + *cp1++ = ' '; + *cp1++ = ' '; + *cp1++ = ' '; + + /* output the list of buffers */ + while (bp != 0) + { + if ((bp->b_flag & BFTEMP) != 0) + { /* Skip magic ones */ + bp = bp->b_bufp; + continue; + } + cp1 = &line[0]; /* Start at left edge */ + + /* output status of ACTIVE flag (has the file been read in? */ + if (bp->b_active == TRUE) /* "@" if activated */ + *cp1++ = '@'; + else + *cp1++ = ' '; + + /* output status of changed flag */ + if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */ + *cp1++ = '*'; + else + *cp1++ = ' '; + *cp1++ = ' '; /* Gap */ + + nbytes = 0; /* Count bytes in buf */ + lp = lforw(bp->b_linep); + while (lp != bp->b_linep) + { + nbytes += llength(lp) + 1; + lp = lforw(lp); + } + itoa(b, 6, nbytes); /* 6 digit buffer size */ + cp2 = &b[0]; + while ((c = *cp2++) != 0) + *cp1++ = (char)c; + *cp1++ = ' '; /* Gap */ + cp2 = &bp->b_bname[0]; /* Buffer name */ + while ((c = *cp2++) != 0) + *cp1++ = (char)c; + cp2 = &bp->b_fname[0]; /* File name */ + if (*cp2 != 0) + { + while (cp1 < &line[2 + 1 + 5 + 1 + 6 + 1 + NBUFN]) /* XXX ??? */ + *cp1++ = ' '; + while ((c = *cp2++) != 0) + { + if (cp1 < &line[128 - 1]) + *cp1++ = (char)c; + } + } + *cp1 = 0; /* Add to the buffer */ + if (addline(line) == FALSE) + return (FALSE); + bp = bp->b_bufp; + } + return (TRUE); /* All done */ +} + +void itoa(char buf[], int width, int num) +{ + buf[width] = 0; /* End of string */ + while (num >= 10) + { /* Conditional digits */ + buf[--width] = (char)((num % 10) + '0'); + num /= 10; + } + buf[--width] = (char)(num + '0'); /* Always 1 digit */ + while (width != 0) /* Pad with blanks */ + buf[--width] = ' '; +} + +/* + * The argument "text" points to a string. Append this line to the buffer list + * buffer. Handcraft the EOL on the end. Return TRUE if it worked and FALSE if + * you ran out of room. + */ +int addline(char *text) +{ + LINE *lp; + int ntext, i; + + ntext = strlen(text); + if ((lp = lalloc(ntext)) == NULL) + return (FALSE); + for (i = 0; i < ntext; ++i) + lputc(lp, i, text[i]); + blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */ + lp->l_bp = blistp->b_linep->l_bp; + blistp->b_linep->l_bp = lp; + lp->l_fp = blistp->b_linep; + if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ + blistp->b_dotp = lp; /* move it to new line */ + return (TRUE); +} + +/* + * Look through the list of buffers. Return TRUE if there are any changed + * buffers. Buffers that hold magic internal stuff are not considered; who + * cares if the list of buffer names is hacked. Return FALSE if no buffers + * have been changed. + */ +int anycb() +{ + BUFFER *bp; + + bp = bheadp; + while (bp != NULL) + { + if ((bp->b_flag & BFTEMP) == 0 && (bp->b_flag & BFCHG) != 0) + return (TRUE); + bp = bp->b_bufp; + } + return (FALSE); +} + +/* + * Find a buffer, by name. Return a pointer to the BUFFER structure associated + * with it. If the named buffer is found, but is a TEMP buffer (like the + * buffer list) conplain. If the buffer is not found and the "cflag" is TRUE, + * create it. The "bflag" is the settings for the flags in in buffer. + */ +BUFFER* bfind(char *bname, int cflag, int bflag) +{ + BUFFER *bp, *sb; + LINE *lp; + + bp = bheadp; + while (bp != 0) + { + if (strcmp(bname, bp->b_bname) == 0) + { + if ((bp->b_flag & BFTEMP) != 0) + { + mlwrite ("Cannot select builtin buffer"); + return (0); + } + return (bp); + } + bp = bp->b_bufp; + } + if (cflag != FALSE) + { + if ((bp = (BUFFER *) malloc(sizeof(BUFFER))) == NULL) + return (0); + if ((lp = lalloc(0)) == NULL) + { + free(bp); + return (BUFFER*)0; + } + /* find the place in the list to insert this buffer */ + if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) + { + /* insert at the begining */ + bp->b_bufp = bheadp; + bheadp = bp; + } + else + { + sb = bheadp; + while (sb->b_bufp != 0) + { + if (strcmp(sb->b_bufp->b_bname, bname) > 0) + break; + sb = sb->b_bufp; + } + + /* and insert it */ + bp->b_bufp = sb->b_bufp; + sb->b_bufp = bp; + } + + /* and set up the other buffer fields */ + bp->b_active = TRUE; + bp->b_dotp = lp; + bp->b_doto = 0; + bp->b_markp = 0; + bp->b_marko = 0; + bp->b_flag = (char)bflag; + bp->b_nwnd = 0; + bp->b_linep = lp; + bp->b_lines = 1; + strncpy(bp->b_fname, "", 1); + strncpy(bp->b_bname, bname, NBUFN); + lp->l_fp = lp; + lp->l_bp = lp; + } + return (bp); +} + +/* + * This routine blows away all of the text in a buffer. If the buffer is + * marked as changed then we ask if it is ok to blow it away; this is to save + * the user the grief of losing text. The window chain is nearly always wrong + * if this gets called; the caller must arrange for the updates that are + * required. Return TRUE if everything looks good. + */ +int bclear(BUFFER *bp) +{ + LINE *lp; + int s; + + if ((bp->b_flag & BFTEMP) == 0 /* Not scratch buffer */ + && (bp->b_flag & BFCHG) != 0 /* Something changed */ + && (s = mlyesno("Discard changes")) != TRUE) + return (s); + bp->b_flag &= ~BFCHG; /* Not changed */ + while ((lp = lforw(bp->b_linep)) != bp->b_linep) + lfree(lp); + bp->b_dotp = bp->b_linep; /* Fix "." */ + bp->b_doto = 0; + bp->b_markp = 0; /* Invalidate "mark" */ + bp->b_marko = 0; + bp->b_lines = 1; + return (TRUE); +} diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c new file mode 100644 index 0000000..721425d --- /dev/null +++ b/src/cmd/emg/display.c @@ -0,0 +1,1015 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file handle redisplay. There are two halves, the ones + * that update the virtual display screen, and the ones that make the physical + * display screen the same as the virtual display screen. These functions use + * hints that are left in the windows by the commands + */ + +#include +#include +#include +#include "estruct.h" +#include "edef.h" + +extern int typeahead(); +extern int ctrlg(); +extern int getccol(); + +void movecursor(int row, int col); +void mlerase(); +void vtinit(); +void vttidy(); +void vtmove(int row, int col); +void vtputc(int c); +void vtpute(int c); +int vtputs(const char *s); +void vteeol(); +void update(); +void updext(); +void updateline(int row, char vline[], char pline[], short *flags); +void modeline(WINDOW *wp); +void upmode(); +int mlyesno(char *prompt); +int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar); +int mlreply(char *prompt, char *buf, int nbuf); +void mlwrite(); +void mlputs(char *s); +void mlputi(int i, int r); +void mlputli(long l, int r); + +typedef struct VIDEO { + short v_flag; /* Flags */ + char v_text[1]; /* Screen data */ +} VIDEO; + +#define VFCHG 0x0001 /* Changed flag */ +#define VFEXT 0x0002 /* extended (beyond column 80) */ +#define VFREV 0x0004 /* reverse video status */ +#define VFREQ 0x0008 /* reverse video request */ + +int vtrow = 0; /* Row location of SW cursor */ +int vtcol = 0; /* Column location of SW cursor */ +int ttrow = HUGE; /* Row location of HW cursor */ +int ttcol = HUGE; /* Column location of HW cursor */ +int lbound = 0; /* leftmost column of line being displayed */ + +VIDEO **vscreen; /* Virtual screen */ +VIDEO **pscreen; /* Physical screen */ + +/* + * Send a command to the terminal to move the hardware cursor to row "row" and + * column "col". The row and column arguments are origin 0. Optimize out + * random calls. Update "ttrow" and "ttcol". + */ +void movecursor(int row, int col) +{ + if (row != ttrow || col != ttcol) + { + ttrow = row; + ttcol = col; + (*term.t_move) (row, col); + } +} + +/* + * Erase the message line. This is a special routine because the message line + * is not considered to be part of the virtual screen. It always works + * immediately; the terminal buffer is flushed via a call to the flusher. + */ +void mlerase() +{ + int i; + + movecursor(term.t_nrow, 0); + if (eolexist == TRUE) + (*term.t_eeol) (); + else + { + for (i = 0; i < term.t_ncol - 1; i++) + (*term.t_putchar) (' '); + movecursor(term.t_nrow, 1); /* force the move! */ + movecursor(term.t_nrow, 0); + } + (*term.t_flush) (); + mpresf = FALSE; +} + +/* + * Initialize the data structures used by the display code. The edge vectors + * used to access the screens are set up. The operating system's terminal I/O + * channel is set up. All the other things get initialized at compile time. + * The original window has "WFCHG" set, so that it will get completely redrawn + * on the first call to "update". + */ +void vtinit() +{ + int i; + VIDEO *vp; + + (*term.t_open) (); + (*term.t_rev) (FALSE); + vscreen = (VIDEO **) malloc(term.t_nrow * sizeof(VIDEO *)); + + if (vscreen == NULL) + exit (1); + + pscreen = (VIDEO **) malloc(term.t_nrow * sizeof(VIDEO *)); + + if (pscreen == NULL) + exit (1); + + for (i = 0; i < term.t_nrow; ++i) + { + vp = (VIDEO *) malloc(sizeof(VIDEO) + term.t_ncol); + + if (vp == NULL) + exit (1); + + vp->v_flag = 0; + vscreen[i] = vp; + vp = (VIDEO *) malloc(sizeof(VIDEO) + term.t_ncol); + + if (vp == NULL) + exit (1); + + vp->v_flag = 0; + pscreen[i] = vp; + } +} + +/* + * Clean up the virtual terminal system, in anticipation for a return to the + * operating system. Move down to the last line and clear it out (the next + * system prompt will be written in the line). Shut down the channel to the + * terminal. + */ +void vttidy() +{ + mlerase(); + movecursor(term.t_nrow, 0); + (*term.t_close) (); +} + +/* + * Set the virtual cursor to the specified row and column on the virtual + * screen. There is no checking for nonsense values; this might be a good idea + * during the early stages. + */ +void vtmove(int row, int col) +{ + vtrow = row; + vtcol = col; +} + +/* + * Write a character to the virtual screen. The virtual row and column are + * updated. If the line is too long put a "$" in the last column. This routine + * only puts printing characters into the virtual terminal buffers. Only + * column overflow is checked. + */ +void vtputc(int c) +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) + { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } + else if (c == '\t') + { + do + { + vtputc(' '); + } + while ((vtcol & 0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtputc('^'); + vtputc(c ^ 0x40); + } + else + vp->v_text[vtcol++] = c; +} + +/* put a character to the virtual screen in an extended line. If we are not + * yet on left edge, don't print it yet. check for overflow on the right + * margin + */ +void vtpute(int c) +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + + if (vtcol >= term.t_ncol) + { + vtcol = (vtcol + 0x07) & ~0x07; + vp->v_text[term.t_ncol - 1] = '$'; + } + else if (c == '\t') + { + do + { + vtpute(' '); + } + while (((vtcol + lbound) & 0x07) != 0); + } + else if (c < 0x20 || c == 0x7F) + { + vtpute('^'); + vtpute(c ^ 0x40); + } + else + { + if (vtcol >= 0) + vp->v_text[vtcol] = c; + ++vtcol; + } +} + +/* + * Output a string to the mode line, report how long it was. + * From OpenBSD mg. + */ +int vtputs(const char *s) +{ + int n = 0; + + while (*s != '\0') { + vtputc(*s++); + ++n; + } + return (n); +} + +/* + * [In the virtual screen] Erase from the end of the software cursor to the + * end of the line on which the software cursor is located. + */ +void vteeol() +{ + VIDEO *vp; + + vp = vscreen[vtrow]; + while (vtcol < term.t_ncol) + vp->v_text[vtcol++] = ' '; +} + +/* + * Make sure that the display is right. This is a three part process. First, + * scan through all of the windows looking for dirty ones. Check the framing, + * and refresh the screen. Second, make sure that "currow" and "curcol" are + * correct for the current window. Third, make the virtual and physical + * screens the same + */ +void update() +{ + VIDEO *vp1, *vp2; + LINE *lp; + WINDOW *wp; + int i, j, c; + + if (typeahead()) + return; + + /* update the reverse video flags for any mode lines out there */ + for (i = 0; i < term.t_nrow; ++i) + vscreen[i]->v_flag &= ~VFREQ; + + wp = wheadp; + while (wp != NULL) + { + vscreen[wp->w_toprow + wp->w_ntrows]->v_flag |= VFREQ; + wp = wp->w_wndp; + } + + wp = wheadp; + while (wp != NULL) + { + /* Look at any window with update flags set on */ + if (wp->w_flag != 0) + { + /* If not force reframe, check the framing */ + if ((wp->w_flag & WFFORCE) == 0) + { + lp = wp->w_linep; + for (i = 0; i < wp->w_ntrows; ++i) + { + if (lp == wp->w_dotp) + goto out; + if (lp == wp->w_bufp->b_linep) + break; + lp = lforw(lp); + } + } + /* Not acceptable, better compute a new value for the line at the top + * of the window. Then set the "WFHARD" flag to force full redraw */ + i = wp->w_force; + if (i > 0) + { + --i; + if (i >= wp->w_ntrows) + i = wp->w_ntrows - 1; + } + else if (i < 0) + { + i += wp->w_ntrows; + if (i < 0) + i = 0; + } + else + i = wp->w_ntrows / 2; + lp = wp->w_dotp; + while (i != 0 && lback(lp) != wp->w_bufp->b_linep) + { + --i; + lp = lback(lp); + } + wp->w_linep = lp; + wp->w_flag |= WFHARD; /* Force full */ + + out: + /* Try to use reduced update. Mode line update has its own special + * flag. The fast update is used if the only thing to do is within + * the line editing */ + lp = wp->w_linep; + i = wp->w_toprow; + if ((wp->w_flag & ~WFMODE) == WFEDIT) + { + while (lp != wp->w_dotp) + { + ++i; + lp = lforw(lp); + } + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + vteeol(); + } + else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0) + { + while (i < wp->w_toprow + wp->w_ntrows) + { + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + /* if line has been changed */ + if (lp != wp->w_bufp->b_linep) + { + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + lp = lforw(lp); + } + vteeol(); + ++i; + } + } + } + modeline(wp); /* always update the modeline so line number is correct */ + wp->w_flag = 0; + wp->w_force = 0; + + wp = wp->w_wndp; /* and onward to the next window */ + } + + /* Always recompute the row and column number of the hardware cursor. This + * is the only update for simple moves */ + lp = curwp->w_linep; + currow = curwp->w_toprow; + while (lp != curwp->w_dotp) + { + ++currow; + lp = lforw(lp); + } + + curcol = 0; + i = 0; + while (i < curwp->w_doto) + { + c = lgetc(lp, i++); + if (c == '\t') + curcol |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++curcol; + ++curcol; + } + if (curcol >= term.t_ncol - 1) + { /* extended line */ + /* flag we are extended and changed */ + vscreen[currow]->v_flag |= VFEXT | VFCHG; + updext(); /* and output extended line */ + } + else + lbound = 0; /* not extended line */ + + /* make sure no lines need to be de-extended because the cursor is no + * longer on them */ + + wp = wheadp; + + while (wp != NULL) + { + lp = wp->w_linep; + i = wp->w_toprow; + + while (i < wp->w_toprow + wp->w_ntrows) + { + if (vscreen[i]->v_flag & VFEXT) + { + /* always flag extended lines as changed */ + vscreen[i]->v_flag |= VFCHG; + if ((wp != curwp) || (lp != wp->w_dotp) || + (curcol < term.t_ncol - 1)) + { + vtmove(i, 0); + for (j = 0; j < llength(lp); ++j) + vtputc (lgetc(lp, j)); + vteeol(); + /* this line no longer is extended */ + vscreen[i]->v_flag &= ~VFEXT; + } + } + lp = lforw(lp); + ++i; + } + /* and onward to the next window */ + wp = wp->w_wndp; + } + + /* Special hacking if the screen is garbage. Clear the hardware screen, and + * update your copy to agree with it. Set all the virtual screen change + * bits, to force a full update */ + if (sgarbf != FALSE) + { + for (i = 0; i < term.t_nrow; ++i) + { + vscreen[i]->v_flag |= VFCHG; + vp1 = pscreen[i]; + for (j = 0; j < term.t_ncol; ++j) + vp1->v_text[j] = ' '; + } + + movecursor(0, 0); /* Erase the screen */ + (*term.t_eeop) (); + sgarbf = FALSE; /* Erase-page clears */ + mpresf = FALSE; /* the message area */ + } + /* Make sure that the physical and virtual displays agree. Unlike before, + * the "updateline" code is only called with a line that has been updated + * for sure */ + for (i = 0; i < term.t_nrow; ++i) + { + vp1 = vscreen[i]; + + /* for each line that needs to be updated, or that needs its reverse + * video status changed, call the line updater */ + j = vp1->v_flag; + if (((j & VFCHG) != 0) || (((j & VFREV) == 0) != ((j & VFREQ) == 0))) + { + if (typeahead()) + return; + vp2 = pscreen[i]; + updateline(i, &vp1->v_text[0], &vp2->v_text[0], &vp1->v_flag); + } + } + + /* Finally, update the hardware cursor and flush out buffers */ + movecursor(currow, curcol - lbound); + (*term.t_flush) (); +} + +/* updext: update the extended line which the cursor is currently on at a + * column greater than the terminal width. The line will be scrolled right or + * left to let the user see where the cursor is + */ +void updext() +{ + LINE *lp; /* pointer to current line */ + int rcursor; /* real cursor location */ + int j; /* index into line */ + + /* calculate what column the real cursor will end up in */ + rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; + lbound = curcol - rcursor + 1; + + /* scan through the line outputing characters to the virtual screen */ + /* once we reach the left edge */ + vtmove(currow, -lbound); /* start scanning offscreen */ + lp = curwp->w_dotp; /* line to output */ + for (j = 0; j < llength(lp); ++j) /* until the end-of-line */ + vtpute (lgetc(lp, j)); + /* truncate the virtual line */ + vteeol(); + /* and put a '$' in column 1 */ + vscreen[currow]->v_text[0] = '$'; +} + +/* + * Update a single line. This does not know how to use insert or delete + * character sequences; we are using VT52 functionality. Update the physical + * row and column variables. It does try an exploit erase to end of line. + */ +void updateline(int row, char vline[], char pline[], short *flags) +{ + char *cp1, *cp2, *cp3, *cp4, *cp5; + int nbflag; /* non-blanks to the right flag? */ + int rev; /* reverse video flag */ + int req; /* reverse video request flag */ + + /* set up pointers to virtual and physical lines */ + cp1 = &vline[0]; + cp2 = &pline[0]; + + /* if we need to change the reverse video status of the current line, we + * need to re-write the entire line */ + rev = *flags & VFREV; + req = *flags & VFREQ; + if (rev != req) + { + movecursor(row, 0); /* Go to start of line */ + (*term.t_rev) (req != FALSE); /* set rev video if needed */ + + /* scan through the line and dump it to the screen and the virtual + * screen array */ + cp3 = &vline[term.t_ncol]; + while (cp1 < cp3) + { + (*term.t_putchar) (*cp1); + ++ttcol; + *cp2++ = *cp1++; + } + (*term.t_rev) (FALSE); /* turn rev video off */ + + /* update the needed flags */ + *flags &= ~VFCHG; + if (req) + *flags |= VFREV; + else + *flags &= ~VFREV; + return; + } + + /* advance past any common chars at the left */ + while (cp1 != &vline[term.t_ncol] && cp1[0] == cp2[0]) + { + ++cp1; + ++cp2; + } + + /* This can still happen, even though we only call this routine on changed + * lines. A hard update is always done when a line splits, a massive change + * is done, or a buffer is displayed twice. This optimizes out most of the + * excess updating. A lot of computes are used, but these tend to be hard + * operations that do a lot of update, so I don't really care */ + /* if both lines are the same, no update needs to be done */ + if (cp1 == &vline[term.t_ncol]) + return; + + /* find out if there is a match on the right */ + nbflag = FALSE; + cp3 = &vline[term.t_ncol]; + cp4 = &pline[term.t_ncol]; + + while (cp3[-1] == cp4[-1]) + { + --cp3; + --cp4; + if (cp3[0] != ' ') /* Note if any nonblank */ + nbflag = TRUE; /* in right match */ + } + + cp5 = cp3; + + if (nbflag == FALSE && eolexist == TRUE) + { /* Erase to EOL ? */ + while (cp5 != cp1 && cp5[-1] == ' ') + --cp5; + if (cp3 - cp5 <= 3) /* Use only if erase is */ + cp5 = cp3; /* fewer characters */ + } + movecursor (row, cp1 - &vline[0]); /* Go to start of line */ + + while (cp1 != cp5) + { /* Ordinary */ + (*term.t_putchar) (*cp1); + ++ttcol; + *cp2++ = *cp1++; + } + + if (cp5 != cp3) + { /* Erase */ + (*term.t_eeol) (); + while (cp1 != cp3) + *cp2++ = *cp1++; + } + *flags &= ~VFCHG; /* flag this line is changed */ +} + +/* + * Redisplay the mode line for the window pointed to by the "wp". This is the + * only routine that has any idea of how the modeline is formatted. You can + * change the modeline format by hacking at this routine. Called by "update" + * any time there is a dirty window. + */ +void modeline(WINDOW *wp) +{ + BUFFER *bp; + int lchar; /* character to draw line in buffer with */ + int n; /* cursor position count */ + int len; /* line/column display check */ + char sl[25]; /* line/column display (probably overkill) */ + + n = wp->w_toprow + wp->w_ntrows; /* Location */ + vscreen[n]->v_flag |= VFCHG; /* Redraw next time */ + vtmove(n, 0); /* Seek to right line */ + if (wp == curwp) /* mark the current buffer */ + lchar = '='; + else + if (revexist) + lchar = ' '; + else + lchar = '-'; + + vtputc(lchar); + bp = wp->w_bufp; + + if ((bp->b_flag & BFCHG) != 0) /* "*" if changed */ + vtputc('*'); + else + vtputc(lchar); + + n = 2; + /* This is the version string. Do not forget to + * increment when releasing a new version. */ + n += vtputs(" emg 1.5 "); + + vtputc(lchar); + vtputc(lchar); + vtputc(' '); + n += 3; + + n += vtputs(&(bp->b_bname[0])); + + vtputc(' '); + vtputc(lchar); + vtputc(lchar); + n += 3; + + if (bp->b_fname[0] != 0) /* File name */ + { + vtputc(' '); + ++n; + n += vtputs("File: "); + + n += vtputs(&(bp->b_fname[0])); + + vtputc(' '); + vtputc(lchar); + vtputc(lchar); + n += 3; + } + + len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", + ((wp->w_dotline +1) / bp->b_lines), + (wp->w_dotline + 1), getccol(FALSE)); + if (len < sizeof(sl) && len != -1) + n += vtputs(sl); + + while (n < term.t_ncol) /* Pad to full width */ + { + vtputc(lchar); + ++n; + } +} + +/* update all the mode lines */ +void upmode() +{ + WINDOW *wp; + + wp = wheadp; + while (wp != NULL) + { + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } +} + +/* + * Ask a yes or no question in the message line. Return either TRUE, FALSE, or + * ABORT. The ABORT status is returned if the user bumps out of the question + * with a ^G. Used any time a confirmation is required. + */ +int mlyesno(char *prompt) +{ + char c; /* input character */ + char buf[NPAT]; /* prompt to user */ + + for (;;) + { + /* build and prompt the user */ + strncpy(buf, prompt, 60); + + strncat(buf, " [y/n]? ", 9); + mlwrite(buf); + + /* get the responce */ + c = (*term.t_getchar) (); + if (c == BELL) /* Bail out! */ + return (ABORT); + if (c == 'y' || c == 'Y') + return (TRUE); + if (c == 'n' || c == 'N') + return (FALSE); + } +} + +/* A more generalized prompt/reply function allowing the caller to specify the + * proper terminator. If the terminator is not a return ('\n') it will echo as + * "" + */ +int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar) +{ + int cpos, i, c; + + cpos = 0; + + if (kbdmop != NULL) + { + while ((c = *kbdmop++) != '\0') + buf[cpos++] = c; + buf[cpos] = 0; + if (buf[0] == 0) + return (FALSE); + return (TRUE); + } + mlwrite(prompt); + + for (;;) + { + /* get a character from the user. if it is a change it to a */ + c = (*term.t_getchar) (); + if (c == 0x0d) + c = '\n'; + + if (c == eolchar) + { + buf[cpos++] = 0; + + if (kbdmip != NULL) + { + if (kbdmip + cpos > &kbdm[NKBDM - 3]) + { + ctrlg(FALSE, 0); + (*term.t_flush) (); + return (ABORT); + } + for (i = 0; i < cpos; ++i) + *kbdmip++ = buf[i]; + } + (*term.t_putchar) ('\r'); + ttcol = 0; + (*term.t_flush) (); + + if (buf[0] == 0) + return (FALSE); + + return (TRUE); + + } + else if (c == 0x07) + { /* Bell, abort */ + (*term.t_putchar) ('^'); + (*term.t_putchar) ('G'); + ttcol += 2; + ctrlg (FALSE, 0); + (*term.t_flush) (); + return (ABORT); + } + else if (c == 0x7F || c == 0x08) + { /* rubout/erase */ + if (cpos != 0) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + + if (buf[--cpos] < 0x20) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + } + if (buf[cpos] == '\n') + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + (*term.t_putchar) ('\b'); + --ttcol; + --ttcol; + } + (*term.t_flush) (); + } + } + else if (c == 0x15) + { /* C-U, kill */ + while (cpos != 0) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + if (buf[--cpos] < 0x20) + { + (*term.t_putchar) ('\b'); + (*term.t_putchar) (' '); + (*term.t_putchar) ('\b'); + --ttcol; + } + } + (*term.t_flush) (); + } + else + { + if (cpos < nbuf - 1) + { + buf[cpos++] = c; + if ((c < ' ') && (c != '\n')) + { + (*term.t_putchar) ('^'); + ++ttcol; + c ^= 0x40; + } + if (c != '\n') + (*term.t_putchar) (c); + else + { /* put out for */ + (*term.t_putchar) ('<'); + (*term.t_putchar) ('N'); + (*term.t_putchar) ('L'); + (*term.t_putchar) ('>'); + ttcol += 3; + } + ++ttcol; + (*term.t_flush) (); + } + } + } +} + +/* + * Write a prompt into the message line, then read back a response. Keep track + * of the physical position of the cursor. If we are in a keyboard macro throw + * the prompt away, and return the remembered response. This lets macros run + * at full speed. The reply is always terminated by a carriage return. Handle + * erase, kill, and abort keys. + */ +int mlreply(char *prompt, char *buf, int nbuf) +{ + return(mlreplyt (prompt, buf, nbuf, '\n')); +} + +/* + * Write a message into the message line. Keep track of the physical cursor + * position. A small class of printf like format items is handled. Assumes the + * stack grows down; this assumption is made by the "++" in the argument scan + * loop. Set the "message line" flag TRUE. + */ +void mlwrite(char *fmt, int arg) +{ + int c; + char *ap; + + if (eolexist == FALSE) + { + mlerase(); + (*term.t_flush) (); + } + movecursor(term.t_nrow, 0); + ap = (char *) &arg; + while ((c = *fmt++) != 0) + { + if (c != '%') + { + (*term.t_putchar) (c); + ++ttcol; + } + else + { + c = *fmt++; + switch (c) + { + case 'd': + mlputi(*(int *) ap, 10); + ap += sizeof(int); + break; + + case 'o': + mlputi(*(int *) ap, 8); + ap += sizeof(int); + break; + + case 'x': + mlputi(*(int *) ap, 16); + ap += sizeof(int); + break; + + case 'D': + mlputli(*(long *) ap, 10); + ap += sizeof(long); + break; + + case 's': + mlputs(*(char **) &ap); + ap += sizeof(char *); + break; + + case 'c': + (*term.t_putchar) (*ap); + ++ttcol; + ap += sizeof(char *); + break; + + default: + (*term.t_putchar) (c); + ++ttcol; + } + } + } + if (eolexist == TRUE) + (*term.t_eeol) (); + (*term.t_flush) (); + mpresf = TRUE; +} + +/* + * Write out a string. Update the physical cursor position. This assumes that + * the characters in the string all have width "1"; if this is not the case + * things will get screwed up a little. + */ +void mlputs(char *s) +{ + int c; + + while ((c = *s++) != 0) + { + (*term.t_putchar) (c); + ++ttcol; + } +} + +/* + * Write out an integer, in the specified radix. Update the physical cursor + * position. This will not handle any negative numbers; maybe it should. + */ +void mlputi(int i, int r) +{ + int q; + static char hexdigits[] = "0123456789abcdef"; + + if (i < 0) + { + i = -i; + (*term.t_putchar) ('-'); + } + q = i / r; + + if (q != 0) + mlputi(q, r); + + (*term.t_putchar) (hexdigits[i % r]); + ++ttcol; +} + +/* + * do the same except as a long integer. + */ +void mlputli(long l, int r) +{ + long q; + + if (l < 0) + { + l = -l; + (*term.t_putchar) ('-'); + } + q = l / r; + + if (q != 0) + mlputli(q, r); + + (*term.t_putchar) ((int) (l % r) + '0'); + ++ttcol; +} + diff --git a/src/cmd/emg/ebind.h b/src/cmd/emg/ebind.h new file mode 100644 index 0000000..a047139 --- /dev/null +++ b/src/cmd/emg/ebind.h @@ -0,0 +1,75 @@ +/* This file is in the public domain. */ + +/* + * This table is *roughly* in ASCII order, left to right across the + * characters of the command. This expains the funny location of the + * control-X commands. + */ + +KEYTAB keytab[] = { + {CTRL | '@', setmark}, + {CTRL | 'A', gotobol}, + {CTRL | 'B', backchar}, + {CTRL | 'D', forwdel}, + {CTRL | 'E', gotoeol}, + {CTRL | 'F', forwchar}, + {CTRL | 'G', ctrlg}, + {CTRL | 'H', backdel}, + {CTRL | 'I', tab}, + {CTRL | 'K', killtext}, + {CTRL | 'L', refresh}, + {CTRL | 'M', newline}, + {CTRL | 'N', forwline}, + {CTRL | 'O', openline}, + {CTRL | 'P', backline}, + {CTRL | 'Q', quote}, + {CTRL | 'R', backsearch}, + {CTRL | 'S', forwsearch}, + {CTRL | 'T', twiddle}, + {CTRL | 'W', killregion}, + {CTRL | 'Y', yank}, + {CTLX | '(', ctlxlp}, + {CTLX | ')', ctlxrp}, + {CTLX | '1', onlywind}, + {CTLX | '2', splitwind}, + {CTLX | 'B', usebuffer}, + {CTLX | 'E', ctlxe}, + {CTLX | 'F', setfillcol}, + {CTLX | 'K', killbuffer}, + {CTLX | 'N', filename}, + {CTLX | 'O', nextwind}, + {CTLX | 'S', filesave}, /* non-standard */ + {CTLX | 'Q', quote}, /* non-standard */ + {CTLX | 'X', nextbuffer}, + {CTLX | '^', enlargewind}, + {CTLX | CTRL | 'B', listbuffers}, + {CTLX | CTRL | 'C', quit}, + {CTLX | CTRL | 'F', filefind}, + {CTLX | CTRL | 'I', insfile}, + {CTLX | CTRL | 'R', fileread}, + {CTLX | CTRL | 'S', filesave}, + {CTLX | CTRL | 'W', filewrite}, + {META | ' ', setmark}, + {META | '%', qreplace}, + {META | '.', setmark}, + {META | '<', gotobob}, + {META | '>', gotoeob}, + {META | 'B', backword}, + {META | 'C', capword}, + {META | 'D', delfword}, + {META | 'F', forwword}, + {META | 'G', setline}, /* non-standard */ + {META | 'L', lowerword}, + {META | 'R', sreplace}, + {META | 'S', forwsearch}, /* non-standard */ + {META | 'U', upperword}, + {META | 'W', copyregion}, + {META | 'Z', quickexit}, + {META | 0x7F, delbword}, + {META | CTRL | 'H', delbword}, + {META | CTRL | 'N', namebuffer}, + {0x7F, backdel}, + {META | '[', extendedcmd}, + {META | 'O', extendedcmd}, + {0, 0} +}; diff --git a/src/cmd/emg/edef.h b/src/cmd/emg/edef.h new file mode 100644 index 0000000..dd59b1e --- /dev/null +++ b/src/cmd/emg/edef.h @@ -0,0 +1,78 @@ +/* This file is in the public domain. */ + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#ifdef maindef +/* + * for MAIN.C + * initialized global definitions + */ + +short kbdm[NKBDM] = {CTLX | ')'}; /* Macro */ +int fillcol = 72; /* Current fill column */ +char pat[NPAT]; /* Search pattern */ +char rpat[NPAT]; /* replacement pattern */ +int revexist = FALSE; +int eolexist = TRUE; /* does clear to EOL exist */ +int sgarbf = TRUE; /* TRUE if screen is garbage */ +int mpresf = FALSE; /* TRUE if message in last line */ + +/* uninitialized global definitions */ + +int currow; /* Cursor row */ +int curcol; /* Cursor column */ +int thisflag; /* Flags, this command */ +int lastflag; /* Flags, last command */ +int curgoal; /* Goal for C-P, C-N */ +WINDOW *curwp; /* Current window */ +BUFFER *curbp; /* Current buffer */ +WINDOW *wheadp; /* Head of list of windows */ +BUFFER *bheadp; /* Head of list of buffers */ +BUFFER *blistp; /* Buffer for C-X C-B */ +short *kbdmip; /* Input pointer for above */ +short *kbdmop; /* Output pointer for above */ + +#else +/* + * for all the other .C files + * initialized global external declarations + */ + +extern int fillcol; /* Fill column */ +extern short kbdm[]; /* Holds kayboard macro data */ +extern char pat[]; /* Search pattern */ +extern char rpat[]; /* Replacement pattern */ +extern int eolexist; /* does clear to EOL exist? */ +extern int revexist; /* does reverse video exist? */ +extern char *modename[]; /* text names of modes */ +extern char modecode[]; /* letters to represent modes */ +extern KEYTAB keytab[]; /* key bind to functions table */ +extern int gmode; /* global editor mode */ +extern int sgarbf; /* State of screen unknown */ +extern int mpresf; /* Stuff in message line */ +extern int clexec; /* command line execution flag */ + +/* initialized global external declarations */ + +extern int currow; /* Cursor row */ +extern int curcol; /* Cursor column */ +extern int thisflag; /* Flags, this command */ +extern int lastflag; /* Flags, last command */ +extern int curgoal; /* Goal for C-P, C-N */ +extern WINDOW *curwp; /* Current window */ +extern BUFFER *curbp; /* Current buffer */ +extern WINDOW *wheadp; /* Head of list of windows */ +extern BUFFER *bheadp; /* Head of list of buffers */ +extern BUFFER *blistp; /* Buffer for C-X C-B */ +extern short *kbdmip; /* Input pointer for above */ +extern short *kbdmop; /* Output pointer for above */ + +#endif + +/* terminal table defined only in TERM.C */ + +#ifndef termdef +extern TERM term; /* Terminal information */ +#endif diff --git a/src/cmd/emg/efunc.h b/src/cmd/emg/efunc.h new file mode 100644 index 0000000..0531b3c --- /dev/null +++ b/src/cmd/emg/efunc.h @@ -0,0 +1,70 @@ +/* This file is in the public domain. */ + +/* EFUNC.H: function declarations and names + * + * This file list all the C code functions used. To add functions, declare it + * here in both the extern function list and the name binding table + */ + +extern int ctrlg(); /* Abort out of things */ +extern int quit(); /* Quit */ +extern int ctlxlp(); /* Begin macro */ +extern int ctlxrp(); /* End macro */ +extern int ctlxe(); /* Execute macro */ +extern int fileread(); /* Get a file, read only */ +extern int filefind(); /* Get a file, read write */ +extern int filewrite(); /* Write a file */ +extern int filesave(); /* Save current file */ +extern int filename(); /* Adjust file name */ +extern int getccol(); /* Get current column */ +extern int gotobol(); /* Move to start of line */ +extern int forwchar(); /* Move forward by characters */ +extern int gotoeol(); /* Move to end of line */ +extern int backchar(); /* Move backward by characters */ +extern int forwline(); /* Move forward by lines */ +extern int backline(); /* Move backward by lines */ +extern int gotobob(); /* Move to start of buffer */ +extern int gotoeob(); /* Move to end of buffer */ +extern int setfillcol(); /* Set fill column */ +extern int setmark(); /* Set mark */ +extern int forwsearch(); /* Search forward */ +extern int backsearch(); /* Search backwards */ +extern int sreplace(); /* search and replace */ +extern int qreplace(); /* search and replace w/query */ +extern int nextwind(); /* Move to the next window */ +extern int prevwind(); /* Move to the previous window */ +extern int onlywind(); /* Make current window only one */ +extern int splitwind(); /* Split current window */ +extern int enlargewind(); /* Enlarge display window */ +extern int shrinkwind(); /* Shrink window */ +extern int listbuffers(); /* Display list of buffers */ +extern int usebuffer(); /* Switch a window to a buffer */ +extern int killbuffer(); /* Make a buffer go away */ +extern int refresh(); /* Refresh the screen */ +extern int twiddle(); /* Twiddle characters */ +extern int tab(); /* Insert tab */ +extern int newline(); /* Insert CR-LF */ +extern int openline(); /* Open up a blank line */ +extern int quote(); /* Insert literal */ +extern int backword(); /* Backup by words */ +extern int forwword(); /* Advance by words */ +extern int forwdel(); /* Forward delete */ +extern int backdel(); /* Backward delete */ +extern int killtext(); /* Kill forward */ +extern int yank(); /* Yank back from killbuffer */ +extern int upperword(); /* Upper case word */ +extern int lowerword(); /* Lower case word */ +extern int capword(); /* Initial capitalize word */ +extern int delfword(); /* Delete forward word */ +extern int delbword(); /* Delete backward word */ +extern int killregion(); /* Kill region */ +extern int copyregion(); /* Copy region to kill buffer */ +extern int quickexit(); /* low keystroke style exit */ +extern int setline(); /* go to a numbered line */ +extern int namebuffer(); /* rename the current buffer */ +extern int deskey(); /* describe a key's binding */ +extern int insfile(); /* insert a file */ +extern int nextbuffer(); /* switch to the next buffer */ +extern int forwhunt(); /* hunt forward for next match */ +extern int backhunt(); /* hunt backwards for next match */ +extern int extendedcmd(); /* parse ANSI/VT100 extended keys */ diff --git a/src/cmd/emg/emg.1 b/src/cmd/emg/emg.1 new file mode 100644 index 0000000..f8cea83 --- /dev/null +++ b/src/cmd/emg/emg.1 @@ -0,0 +1,58 @@ +.\" This file is in the public domain. +.\" +.\" Basic emg man page. +.\" As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. +.\" +.Dd March 23, 2014 +.Os +.Dt EMG 1 +.Sh NAME +.Nm emg +.Nd very small Emacs-like text editor +.Sh SYNOPSIS +.Nm emg +.Op Ar +.Sh DESCRIPTION +.Nm , +or Ersatz Mg, is an Emacs-like text editor designed for memory-constrained +environments. +.Nm +was originally created to fit into an operating environment of 96K of RAM, and +one in which Mg did not fit and Ersatz Emacs did not build. +By combining parts of each, a working editor was created. +.Pp +When invoked without file arguments, +.Nm +creates a +.Qq main +buffer. +This buffer must be renamed +.Ic ( C-x n ) +in order to be saved +.Ic ( C-x C-s ) . +.Pp +As both Ersatz Emacs and Mg are Public Domain, +.Nm +is also Public Domain. +.Sh FILES +There is a chart of key bindings in +.Pa /usr/local/share/doc/emg/emg.keys . +Consulting this file is a must, as +.Nm +does not guarantee keybindings to be identical to other Emacs implementations. +.Sh AUTHORS +.Nm +is a combination of Ersatz Emacs and Mg and therefore all authors for both +deserve credit. +Ersatz Emacs and Mg were combined by +.An Brian Callahan Aq Mt bcallah@openbsd.org +to create +.Nm . +.Sh BUGS +None known. +However, patches are appreciated if any are found. +.Sh TODO +It would be nice to have automatic window resizing. +It would also be nice if +.Nm +could clear the screen when quit, like Mg does. diff --git a/src/cmd/emg/emg.keys b/src/cmd/emg/emg.keys new file mode 100644 index 0000000..6677f1b --- /dev/null +++ b/src/cmd/emg/emg.keys @@ -0,0 +1,147 @@ + emg keybindings (March 16, 2014) + Based on Ersatz Emacs (2000/09/14) + +M- means to use the key prior to using another key +^A means to use the control key at the same time as the 'A' key + +------------------------------------------------------------------------------ + MOVING THE CURSOR + +^F Forward character M-F Forward word +^B Backward character M-B Backward word +^N Next line M-P Front of paragraph +^P Previous line M-N End of paragraph +^A Front of line M-< or [HOME] Start of file +^E End of line M-> or [END] End of file +M-G Go to line Arrow keys are active + +------------------------------------------------------------------------------ + DELETING & INSERTING + +<- Delete previous character M-<- Delete previous word +^D Delete next character M-D Delete next word +^K Delete to end of line ^O Insert line + +------------------------------------------------------------------------------ + FORMATTING & TRANSPOSING + +M-U UPPERCASE word M-C Capitalize word +M-L lowercase word ^T Transpose characters +^Q Quote next key, so that control codes may be entered into text. (or ^X Q) +M-Q Format paragraph so that text is left-justified between margins. +^X F Set the right margin for paragraph formatting to the current position of + the cursor. + +------------------------------------------------------------------------------ + SEARCHING + +^S Search forward from cursor position. Type in a string and end it with + ENTER. Either case matches. (or M-S) +^R As above, but reverse search from cursor position. + +------------------------------------------------------------------------------ + REPLACING + +M-R Replace all instances of first typed-in string with second typed-in + string. +M-% Replace with query. Answer with: + Y replace & continue N no replacement & continue + ! replace the rest ? Get a list of options + . exit and return to entry point + ^G,'q' or exit and remain at current location + +------------------------------------------------------------------------------ + COPYING AND MOVING + +^@ or M- Set mark at current position. +^W Delete region. +M-W Copy region to kill buffer. +^Y Yank back kill buffer at cursor. + +A region is defined as the area between this mark and the current cursor +position. The kill buffer is the text which has been most recently deleted or +copied. + +Generally, the procedure for copying or moving text is: +1) Mark out region using M- at the beginning and move the cursor to + the end. +2) Delete it (with ^W) or copy it (with M-W) into the kill buffer. +3) Move the cursor to the desired location and yank it back (with ^Y). + +------------------------------------------------------------------------------ + MULTIPLE BUFFERS + +A buffer contains a COPY of a document being edited, and must be saved for +changes to be kept. Many buffers may be activated at once. + +^X B Switch to another buffer. +^X ^B Show buffer directory in a window (^X 1 to remove). +^X K Delete a non-displayed buffer. +^X X Switch to next buffer in buffer list. +^X N Change the filename associated with the buffer. +M-^N Change the name of the buffer. + +------------------------------------------------------------------------------ + READING FROM DISK + +^X^F Find file; read into a new buffer created from filename. + (This is the usual way to edit a new file.) +^X^R Read file into current buffer, erasing its previous contents. + No new buffer will be created. +^X^I Insert file into current buffer at cursor's location. + +------------------------------------------------------------------------------ + SAVING TO DISK + +^X^S Save current buffer to disk, using the buffer's filename as the name of + the disk file. Any disk file of that name will be overwritten. (or ^X S) +^X^W Write current buffer to disk. Type in a new filename at the prompt to + write to; it will also become the current buffer's filename. + +------------------------------------------------------------------------------ + MULTIPLE WINDOWS + +Many windows may be visible at once on the screen. Windows may show different +parts of the same buffer, or each may display a different one. + +^X 2 Split the current window in two ^X 1 Show only current window +^X O Move cursor to next window ^X ^ Enlarge current window +M-^V Scroll other window down M-^Z Scroll other window up + +------------------------------------------------------------------------------ + EXITING + +^X^C Exit. Any unsaved files will require confirmation. +M-Z Write out all changed buffers automatically and exit. + +------------------------------------------------------------------------------ + MACROS + +^X ( Start recording a keyboard macro. Typing ^G or an error aborts. +^X ) Stop recording macro. +^X E Execute macro. + +------------------------------------------------------------------------------ + REPEAT & NUMBER PREFIX + +^U or M- + Number prefix and universal repeat. May be followed by an integer + (default = 4) and repeats the next command that many times. + Exceptions follow. +^U^L + Reposition the cursor to a particular screen row; i.e., ^U0^L moves the + cursor and the line it is on to the top of the screen. Negative numbers + are from the bottom of the screen. +^U^X F + Set the right margin to column for paragraph formatting. +^U^X^ + Enlarge a split window by rows. A negative number shrinks the + window. + +------------------------------------------------------------------------------ + SPECIAL KEYS + +^G Cancel current command. +^L Redraws the screen completely. + +------------------------------------------------------------------------------ diff --git a/src/cmd/emg/estruct.h b/src/cmd/emg/estruct.h new file mode 100644 index 0000000..a5a84ef --- /dev/null +++ b/src/cmd/emg/estruct.h @@ -0,0 +1,162 @@ +/* This file is in the public domain. */ + +/* ESTRUCT: Structure and preprocessor */ + +/* internal constants */ +#define NFILEN 80 /* maximum # of bytes, file name */ +#define NBUFN 16 /* maximum # of bytes, buffer name */ +#define NLINE 512 /* maximum # of bytes, line */ +#define NKBDM 256 /* maximum # of strokes, keyboard macro */ +#define NPAT 80 /* maximum # of bytes, pattern */ +#define HUGE 32700 /* Huge number for "impossible" row&col */ + +#define METACH 0x1B /* M- prefix, Control-[, ESC */ +#define BELL 0x07 /* a bell character */ +#define TAB 0x09 /* a tab character */ + +#define CTRL 0x0100 /* Control flag, or'ed in */ +#define META 0x0200 /* Meta flag, or'ed in */ +#define CTLX 0x0400 /* ^X flag, or'ed in */ + +#define FALSE 0 /* False, no, bad, etc */ +#define TRUE 1 /* True, yes, good, etc */ +#define ABORT 2 /* Death, ^G, abort, etc */ + +#define FIOSUC 0 /* File I/O, success */ +#define FIOFNF 1 /* File I/O, file not found */ +#define FIOEOF 2 /* File I/O, end of file */ +#define FIOERR 3 /* File I/O, error */ +#define FIOLNG 4 /* line longer than allowed len */ + +#define CFCPCN 0x0001 /* Last command was C-P, C-N */ +#define CFKILL 0x0002 /* Last command was a kill */ + +/* + * There is a window structure allocated for every active display window. The + * windows are kept in a big list, in top to bottom screen order, with the + * listhead at "wheadp". Each window contains its own values of dot and mark. + * The flag field contains some bits that are set by commands to guide + * redisplay; although this is a bit of a compromise in terms of decoupling, + * the full blown redisplay is just too expensive to run for every input + * character + */ +typedef struct WINDOW +{ + struct WINDOW *w_wndp; /* Next window */ + struct BUFFER *w_bufp; /* Buffer displayed in window */ + struct LINE *w_linep; /* Top line in the window */ + struct LINE *w_dotp; /* Line containing "." */ + long w_doto; /* Byte offset for "." */ + struct LINE *w_markp; /* Line containing "mark" */ + long w_marko; /* Byte offset for "mark" */ + char w_toprow; /* Origin 0 top row of window */ + char w_ntrows; /* # of rows of text in window */ + char w_force; /* If NZ, forcing row */ + char w_flag; /* Flags */ + int w_dotline; /* current line number of dot */ +} WINDOW; + +#define WFFORCE 0x01 /* Window needs forced reframe */ +#define WFMOVE 0x02 /* Movement from line to line */ +#define WFEDIT 0x04 /* Editing within a line */ +#define WFHARD 0x08 /* Better to a full display */ +#define WFMODE 0x10 /* Update mode line */ + +/* + * Text is kept in buffers. A buffer header, described below, exists for every + * buffer in the system. The buffers are kept in a big list, so that commands + * that search for a buffer by name can find the buffer header. There is a + * safe store for the dot and mark in the header, but this is only valid if + * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for + * the buffer is kept in a circularly linked list of lines, with a pointer to + * the header line in "b_linep". Buffers may be "Inactive" which means the + * files accosiated with them have not been read in yet. These get read in at + * "use buffer" time + */ +typedef struct BUFFER +{ + struct BUFFER *b_bufp; /* Link to next BUFFER */ + struct LINE *b_dotp; /* Link to "." LINE structure */ + long b_doto; /* Offset of "." in above LINE */ + struct LINE *b_markp; /* The same as the above two, */ + long b_marko; /* but for the "mark" */ + struct LINE *b_linep; /* Link to the header LINE */ + char b_active; /* window activated flag */ + char b_nwnd; /* Count of windows on buffer */ + char b_flag; /* Flags */ + char b_fname[NFILEN]; /* File name */ + char b_bname[NBUFN]; /* Buffer name */ + int b_lines; /* Number of lines in file */ +} BUFFER; + +#define BFTEMP 0x01 /* Internal temporary buffer */ +#define BFCHG 0x02 /* Changed since last write */ + +/* + * The starting position of a region, and the size of the region in + * characters, is kept in a region structure. Used by the region commands + */ +typedef struct +{ + struct LINE *r_linep; /* Origin LINE address */ + long r_offset; /* Origin LINE offset */ + long r_size; /* Length in characters */ +} REGION; + +/* + * All text is kept in circularly linked lists of "LINE" structures. These + * begin at the header line (which is the blank line beyond the end of the + * buffer). This line is pointed to by the "BUFFER". Each line contains a the + * number of bytes in the line (the "used" size), the size of the text array, + * and the text. The end of line is not stored as a byte; it's implied. Future + * additions will include update hints, and a list of marks into the line + */ +typedef struct LINE +{ + struct LINE *l_fp; /* Link to the next line */ + struct LINE *l_bp; /* Link to the previous line */ + int l_size; /* Allocated size */ + int l_used; /* Used size */ + char l_text[1]; /* A bunch of characters */ +} LINE; + +#define lforw(lp) ((lp)->l_fp) +#define lback(lp) ((lp)->l_bp) +#define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF) +#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) +#define llength(lp) ((lp)->l_used) + +/* + * The editor communicates with the display using a high level interface. A + * "TERM" structure holds useful variables, and indirect pointers to routines + * that do useful operations. The low level get and put routines are here too. + * This lets a terminal, in addition to having non standard commands, have + * funny get and put character code too. The calls might get changed to + * "termp->t_field" style in the future, to make it possible to run more than + * one terminal type + */ +typedef struct +{ + int t_nrow; /* Number of rows */ + int t_ncol; /* Number of columns */ + int t_margin; /* min margin for extended lines */ + int t_scrsiz; /* size of scroll region " */ + void (*t_open) (); /* Open terminal at the start */ + void (*t_close) (); /* Close terminal at end */ + int (*t_getchar) (); /* Get character from keyboard */ + void (*t_putchar) (); /* Put character to display */ + void (*t_flush) (); /* Flush output buffers */ + void (*t_move) (); /* Move the cursor, origin 0 */ + void (*t_eeol) (); /* Erase to end of line */ + void (*t_eeop) (); /* Erase to end of page */ + void (*t_beep) (); /* Beep */ + void (*t_rev) (); /* set reverse video state */ +} TERM; + +/* structure for the table of initial key bindings */ + +typedef struct +{ + short k_code; /* Key code */ + int (*k_fp) (); /* Routine to handle it */ +} KEYTAB; diff --git a/src/cmd/emg/file.c b/src/cmd/emg/file.c new file mode 100644 index 0000000..326b823 --- /dev/null +++ b/src/cmd/emg/file.c @@ -0,0 +1,465 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file handle the reading and writing of disk files. + * All details about the reading and writing of the disk are in "fileio.c" + */ + +#include /* strncpy(3) */ +#include "estruct.h" +#include "edef.h" + +extern int mlreply(char *prompt, char *buf, int nbuf); +extern int swbuffer(BUFFER *bp); +extern void mlwrite(); +extern int bclear(BUFFER *bp); +extern int ffropen(char *fn); +extern int ffgetline(char buf[], int nbuf); +extern int ffwopen(char *fn); +extern int ffclose(); +extern int ffputline(char buf[], int nbuf); +extern BUFFER *bfind(); +extern LINE *lalloc(); + +int fileread(int f, int n); +int insfile(int f, int n); +int filefind(int f, int n); +int getfile(char fname[]); +int readin(char fname[]); +void makename(char bname[], char fname[]); +int filewrite(int f, int n); +int filesave(int f, int n); +int writeout(char *fn); +int filename(int f, int n); +int ifile(char fname[]); + +/* + * Read a file into the current buffer. This is really easy; all you do it + * find the name of the file, and call the standard "read a file into the + * current buffer" code. Bound to "C-X C-R" + */ +int fileread(int f, int n) +{ + int s; + char fname[NFILEN]; + + if ((s = mlreply("Read file: ", fname, NFILEN)) != TRUE) + return (s); + return (readin(fname)); +} + +/* + * Insert a file into the current buffer. This is really easy; all you do it + * find the name of the file, and call the standard "insert a file into the + * current buffer" code. Bound to "C-X C-I". + */ +int insfile(int f, int n) +{ + int s; + char fname[NFILEN]; + + if ((s = mlreply("Insert file: ", fname, NFILEN)) != TRUE) + return (s); + return (ifile(fname)); +} + +/* + * Select a file for editing. Look around to see if you can find the fine in + * another buffer; if you can find it just switch to the buffer. If you cannot + * find the file, create a new buffer, read in the text, and switch to the new + * buffer. Bound to C-X C-F. + */ +int filefind(int f, int n) +{ + char fname[NFILEN]; /* file user wishes to find */ + int s; /* status return */ + + if ((s = mlreply("Find file: ", fname, NFILEN)) != TRUE) + return (s); + return (getfile(fname)); +} + +int getfile(char fname[]) +{ + BUFFER *bp; + LINE *lp; + char bname[NBUFN]; /* buffer name to put file */ + int i, s; + + for (bp = bheadp; bp != (BUFFER*)0; bp = bp->b_bufp) + { + if ((bp->b_flag & BFTEMP) == 0 && strcmp(bp->b_fname, fname) == 0) + { + if (--curbp->b_nwnd == 0) + { + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + swbuffer(bp); + lp = curwp->w_dotp; + i = curwp->w_ntrows / 2; + while (i-- && lback(lp) != curbp->b_linep) + lp = lback(lp); + curwp->w_linep = lp; + curwp->w_flag |= WFMODE | WFHARD; + mlwrite("[Old buffer]"); + return (TRUE); + } + } + makename(bname, fname); /* New buffer name */ + while ((bp = bfind(bname, FALSE, 0)) != (BUFFER*)0) + { + s = mlreply("Buffer name: ", bname, NBUFN); + if (s == ABORT) /* ^G to just quit */ + return (s); + if (s == FALSE) + { /* CR to clobber it */ + makename(bname, fname); + break; + } + } + if (bp == (BUFFER*)0 && (bp = bfind(bname, TRUE, 0)) == (BUFFER*)0) + { + mlwrite("Cannot create buffer"); + return (FALSE); + } + if (--curbp->b_nwnd == 0) + { /* Undisplay */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + } + curbp = bp; /* Switch to it */ + curwp->w_bufp = bp; + curbp->b_nwnd++; + return (readin(fname)); /* Read it in */ +} + +/* + * Read file "fname" into the current buffer, blowing away any text found + * there. Called by both the read and find commands. Return the final status + * of the read. Also called by the mainline, to read in a file specified on + * the command line as an argument. + */ +int readin(char fname[]) +{ + LINE *lp1, *lp2; + WINDOW *wp; + BUFFER *bp; + char line[NLINE]; + int nbytes, s, i; + int nline = 0; /* initialize here to silence a gcc warning */ + int lflag; /* any lines longer than allowed? */ + + bp = curbp; /* Cheap */ + if ((s = bclear(bp)) != TRUE) /* Might be old */ + return (s); + bp->b_flag &= ~(BFTEMP | BFCHG); + strncpy(bp->b_fname, fname, NFILEN); + if ((s = ffropen(fname)) == FIOERR) /* Hard file open */ + goto out; + if (s == FIOFNF) + { /* File not found */ + mlwrite("[New file]"); + goto out; + } + mlwrite("[Reading file]"); + lflag = FALSE; + while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) + { + if (s == FIOLNG) + lflag = TRUE; + nbytes = strlen(line); + if ((lp1 = lalloc(nbytes)) == NULL) + { + s = FIOERR; /* Keep message on the display */ + break; + } + lp2 = lback(curbp->b_linep); + lp2->l_fp = lp1; + lp1->l_fp = curbp->b_linep; + lp1->l_bp = lp2; + curbp->b_linep->l_bp = lp1; + for (i = 0; i < nbytes; ++i) + lputc(lp1, i, line[i]); + ++nline; + } + ffclose(); /* Ignore errors */ + if (s == FIOEOF) + { /* Don't zap message! */ + if (nline != 1) + mlwrite("[Read %d lines]", nline); + else + mlwrite("[Read 1 line]"); + } + if (lflag) + { + if (nline != 1) + mlwrite("[Read %d lines: Long lines wrapped]", nline); + else + mlwrite("[Read 1 line: Long lines wrapped]"); + } + curwp->w_bufp->b_lines = nline; + out: + for (wp = wheadp; wp != NULL; wp = wp->w_wndp) + { + if (wp->w_bufp == curbp) + { + wp->w_linep = lforw(curbp->b_linep); + wp->w_dotp = lforw(curbp->b_linep); + wp->w_doto = 0; + wp->w_markp = NULL; + wp->w_marko = 0; + wp->w_flag |= WFMODE | WFHARD; + } + } + if (s == FIOERR || s == FIOFNF) /* False if error */ + return (FALSE); + return (TRUE); +} + +/* + * Take a file name, and from it fabricate a buffer name. This routine knows + * about the syntax of file names on the target system. I suppose that this + * information could be put in a better place than a line of code. + */ +void makename(char bname[], char fname[]) +{ + char *cp1, *cp2; + + cp1 = &fname[0]; + while (*cp1 != 0) + ++cp1; + + while (cp1 != &fname[0] && cp1[-1] != '/') + --cp1; + cp2 = &bname[0]; + while (cp2 != &bname[NBUFN - 1] && *cp1 != 0 && *cp1 != ';') + *cp2++ = *cp1++; + *cp2 = 0; +} + +/* + * Ask for a file name, and write the contents of the current buffer to that + * file. Update the remembered file name and clear the buffer changed flag. + * This handling of file names is different from the earlier versions, and is + * more compatable with Gosling EMACS than with ITS EMACS. Bound to "C-X C-W". + */ +int filewrite(int f, int n) +{ + WINDOW *wp; + char fname[NFILEN]; + int s; + + if ((s = mlreply("Write file: ", fname, NFILEN)) != TRUE) + return (s); + if ((s = writeout(fname)) == TRUE) + { + strncpy(curbp->b_fname, fname, NFILEN); + curbp->b_flag &= ~BFCHG; + wp = wheadp; /* Update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + } + return (s); +} + +/* + * Save the contents of the current buffer in its associatd file. No nothing + * if nothing has changed (this may be a bug, not a feature). Error if there + * is no remembered file name for the buffer. Bound to "C-X C-S". May get + * called by "C-Z" + */ +int filesave(int f, int n) +{ + WINDOW *wp; + int s; + + if ((curbp->b_flag & BFCHG) == 0) /* Return, no changes */ + return (TRUE); + if (curbp->b_fname[0] == 0) + { /* Must have a name */ + mlwrite("No file name"); + return (FALSE); + } + if ((s = writeout(curbp->b_fname)) == TRUE) + { + curbp->b_flag &= ~BFCHG; + wp = wheadp; /* Update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + } + return (s); +} + +/* + * This function performs the details of file writing. Uses the file + * management routines in the "fileio.c" package. The number of lines written + * is displayed. Sadly, it looks inside a LINE; provide a macro for this. Most + * of the grief is error checking of some sort. + */ +int writeout(char *fn) +{ + LINE *lp; + int nline, s; + + if ((s = ffwopen(fn)) != FIOSUC) /* Open writes message */ + return (FALSE); + mlwrite("[Writing]"); /* tell us were writing */ + lp = lforw(curbp->b_linep); /* First line */ + nline = 0; /* Number of lines */ + while (lp != curbp->b_linep) + { + if ((s = ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) + break; + ++nline; + lp = lforw(lp); + } + if (s == FIOSUC) + { /* No write error */ + s = ffclose(); + if (s == FIOSUC) + { /* No close error */ + if (nline != 1) + mlwrite("[Wrote %d lines]", nline); + else + mlwrite("[Wrote 1 line]"); + } + } + else /* ignore close error */ + ffclose(); /* if a write error */ + if (s != FIOSUC) /* some sort of error */ + return (FALSE); + return (TRUE); +} + +/* + * The command allows the user to modify the file name associated with the + * current buffer. It is like the "f" command in UNIX "ed". The operation is + * simple; just zap the name in the BUFFER structure, and mark the windows as + * needing an update. You can type a blank line at the prompt if you wish. + */ +int filename(int f, int n) +{ + WINDOW *wp; + char fname[NFILEN]; + int s; + + if ((s = mlreply("Name: ", fname, NFILEN)) == ABORT) + return (s); + if (s == FALSE) + strncpy(curbp->b_fname, "", 1); + else + strncpy(curbp->b_fname, fname, NFILEN); + wp = wheadp; /* update mode lines */ + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Insert file "fname" into the current buffer, Called by insert file command. + * Return the final status of the read. + */ +int ifile(char fname[]) +{ + LINE *lp0, *lp1, *lp2; + BUFFER *bp; + char line[NLINE]; + int i, s, nbytes; + int nline = 0; + int lflag; /* any lines longer than allowed? */ + + bp = curbp; /* Cheap */ + bp->b_flag |= BFCHG; /* we have changed */ + bp->b_flag &= ~BFTEMP; /* and are not temporary */ + if ((s = ffropen(fname)) == FIOERR) /* Hard file open */ + goto out; + if (s == FIOFNF) + { /* File not found */ + mlwrite("[No such file]"); + return (FALSE); + } + mlwrite("[Inserting file]"); + + /* back up a line and save the mark here */ + curwp->w_dotp = lback(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = 0; + + lflag = FALSE; + while ((s = ffgetline(line, NLINE)) == FIOSUC || s == FIOLNG) + { + if (s == FIOLNG) + lflag = TRUE; + nbytes = strlen(line); + if ((lp1 = lalloc(nbytes)) == NULL) + { + s = FIOERR; /* keep message on the */ + break; /* display */ + } + lp0 = curwp->w_dotp; /* line previous to insert */ + lp2 = lp0->l_fp; /* line after insert */ + + /* re-link new line between lp0 and lp2 */ + lp2->l_bp = lp1; + lp0->l_fp = lp1; + lp1->l_bp = lp0; + lp1->l_fp = lp2; + + /* and advance and write out the current line */ + curwp->w_dotp = lp1; + for (i = 0; i < nbytes; ++i) + lputc(lp1, i, line[i]); + ++nline; + } + ffclose(); /* Ignore errors */ + curwp->w_markp = lforw(curwp->w_markp); + if (s == FIOEOF) + { /* Don't zap message! */ + if (nline != 1) + mlwrite("[Inserted %d lines]", nline); + else + mlwrite("[Inserted 1 line]"); + } + if (lflag) + { + if (nline != 1) + mlwrite("[Inserted %d lines: Long lines wrapped]", nline); + else + mlwrite("[Inserted 1 line: Long lines wrapped]"); + } + out: + /* advance to the next line and mark the window for changes */ + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_flag |= WFHARD; + + /* copy window parameters back to the buffer structure */ + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curwp->w_doto; + curbp->b_markp = curwp->w_markp; + curbp->b_marko = curwp->w_marko; + + /* we need to update number of lines in the buffer */ + curwp->w_bufp->b_lines += nline; + + if (s == FIOERR) /* False if error */ + return (FALSE); + return (TRUE); +} diff --git a/src/cmd/emg/fileio.c b/src/cmd/emg/fileio.c new file mode 100644 index 0000000..d61b005 --- /dev/null +++ b/src/cmd/emg/fileio.c @@ -0,0 +1,121 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file read and write ASCII files from the disk. All of + * the knowledge about files is here. A better message writing scheme should + * be used + */ + +#include /* fopen(3), et.al. */ +#include "estruct.h" + +extern void mlwrite(); + +int ffropen(char *fn); +int ffwopen(char *fn); +int ffclose(); +int ffputline(char buf[], int nbuf); +int ffgetline(char buf[], int nbuf); + +FILE *ffp; /* File pointer, all functions */ + +/* + * Open a file for reading. + */ +int ffropen(char *fn) +{ + if ((ffp = fopen(fn, "r")) == NULL) + return (FIOFNF); + return (FIOSUC); +} + +/* + * Open a file for writing. Return TRUE if all is well, and FALSE on error + * (cannot create). + */ +int ffwopen(char *fn) +{ + if ((ffp = fopen(fn, "w")) == NULL) + { + mlwrite("Cannot open file for writing"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Close a file. Should look at the status in all systems. + */ +int ffclose() +{ + if (fclose(ffp) != FALSE) + { + mlwrite("Error closing file"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Write a line to the already opened file. The "buf" points to the buffer, + * and the "nbuf" is its length, less the free newline. Return the status. + * Check only at the newline. + */ +int ffputline(char buf[], int nbuf) +{ + int i; + + for (i = 0; i < nbuf; ++i) + fputc(buf[i] & 0xFF, ffp); + + fputc('\n', ffp); + + if (ferror(ffp)) + { + mlwrite("Write I/O error"); + return (FIOERR); + } + return (FIOSUC); +} + +/* + * Read a line from a file, and store the bytes in the supplied buffer. The + * "nbuf" is the length of the buffer. Complain about long lines and lines at + * the end of the file that don't have a newline present. Check for I/O errors + * too. Return status. + */ +int ffgetline(char buf[], int nbuf) +{ + int c, i; + + i = 0; + + while ((c = fgetc(ffp)) != EOF && c != '\n') + { + if (i >= nbuf - 2) + { + buf[nbuf - 2] = c; /* store last char read */ + buf[nbuf - 1] = 0; /* and terminate it */ + mlwrite("File has long lines"); + return (FIOLNG); + } + buf[i++] = c; + } + + if (c == EOF) + { + if (ferror(ffp)) + { + mlwrite("File read error"); + return (FIOERR); + } + if (i != 0) + { + mlwrite("No newline at EOF"); + return (FIOERR); + } + return (FIOEOF); + } + buf[i] = 0; + return (FIOSUC); +} diff --git a/src/cmd/emg/line.c b/src/cmd/emg/line.c new file mode 100644 index 0000000..df05774 --- /dev/null +++ b/src/cmd/emg/line.c @@ -0,0 +1,507 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file are a general set of line management utilities. + * They are the only routines that touch the text. They also touch the buffer + * and window structures, to make sure that the necessary updating gets done. + * There are routines in this file that handle the kill buffer too. It isn't + * here for any good reason. + * + * Note that this code only updates the dot and mark values in the window + * list. Since all the code acts on the current window, the buffer that we are + * editing must be being displayed, which means that "b_nwnd" is non zero, + * which means that the dot and mark values in the buffer headers are + * nonsense + */ + +#include /* malloc(3) */ +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern int backchar(int f, int n); + +LINE* lalloc(int used); +void lfree(LINE *lp); +void lchange(int flag); +int linsert(int n, int c); +int lnewline(); +int ldelete(int n, int kflag); +int ldelnewline(); +void kdelete(); +int kinsert(int c); +int kremove(int n); + +#define NBLOCK 16 /* Line block chunk size */ +#define KBLOCK 1024 /* Kill buffer block size */ + +char *kbufp = NULL; /* Kill buffer data */ +unsigned long kused = 0; /* # of bytes used in KB */ +unsigned long ksize = 0; /* # of bytes allocated in KB */ + +/* + * This routine allocates a block of memory large enough to hold a LINE + * containing "used" characters. The block is always rounded up a bit. Return + * a pointer to the new block, or NULL if there isn't any memory left. Print a + * message in the message line if no space. + */ +LINE* lalloc(int used) +{ + LINE *lp; + int size; + + size = (used + NBLOCK - 1) & ~(NBLOCK - 1); + if (size == 0) /* Assume that an empty */ + size = NBLOCK; /* line is for type-in */ + if ((lp = (LINE *) malloc(sizeof(LINE) + size)) == NULL) + { + mlwrite("Cannot allocate %d bytes", size); + return (NULL); + } + lp->l_size = size; + lp->l_used = used; + return (lp); +} + +/* + * Delete line "lp". Fix all of the links that might point at it (they are + * moved to offset 0 of the next line. Unlink the line from whatever buffer it + * might be in. Release the memory. The buffers are updated too; the magic + * conditions described in the above comments don't hold here + */ +void lfree(LINE *lp) +{ + BUFFER *bp; + WINDOW *wp; + + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp) + wp->w_linep = lp->l_fp; + if (wp->w_dotp == lp) + { + wp->w_dotp = lp->l_fp; + wp->w_doto = 0; + } + if (wp->w_markp == lp) + { + wp->w_markp = lp->l_fp; + wp->w_marko = 0; + } + wp = wp->w_wndp; + } + bp = bheadp; + while (bp != NULL) + { + if (bp->b_nwnd == 0) + { + if (bp->b_dotp == lp) + { + bp->b_dotp = lp->l_fp; + bp->b_doto = 0; + } + if (bp->b_markp == lp) + { + bp->b_markp = lp->l_fp; + bp->b_marko = 0; + } + } + bp = bp->b_bufp; + } + lp->l_bp->l_fp = lp->l_fp; + lp->l_fp->l_bp = lp->l_bp; + free((char *) lp); +} + +/* + * This routine gets called when a character is changed in place in the + * current buffer. It updates all of the required flags in the buffer and + * window system. The flag used is passed as an argument; if the buffer is + * being displayed in more than 1 window we change EDIT t HARD. Set MODE if + * the mode line needs to be updated (the "*" has to be set). + */ +void lchange(int flag) +{ + WINDOW *wp; + + if (curbp->b_nwnd != 1) /* Ensure hard */ + flag = WFHARD; + if ((curbp->b_flag & BFCHG) == 0) + { /* First change, so */ + flag |= WFMODE; /* update mode lines */ + curbp->b_flag |= BFCHG; + } + wp = wheadp; + while (wp != NULL) + { + if (wp->w_bufp == curbp) + wp->w_flag |= flag; + wp = wp->w_wndp; + } +} + +/* + * Insert "n" copies of the character "c" at the current location of dot. In + * the easy case all that happens is the text is stored in the line. In the + * hard case, the line has to be reallocated. When the window list is updated, + * take special care; I screwed it up once. You always update dot in the + * current window. You update mark, and a dot in another window, if it is + * greater than the place where you did the insert. Return TRUE if all is + * well, and FALSE on errors + */ +int linsert(int n, int c) +{ + WINDOW *wp; + LINE *lp1, *lp2, *lp3; + char *cp1, *cp2; + int i, doto; + + lchange(WFEDIT); + lp1 = curwp->w_dotp; /* Current line */ + if (lp1 == curbp->b_linep) + { /* At the end: special */ + if (curwp->w_doto != 0) + { + mlwrite("Bug: linsert"); + return (FALSE); + } + if ((lp2 = lalloc(n)) == NULL) /* Allocate new line */ + return (FALSE); + lp3 = lp1->l_bp; /* Previous line */ + lp3->l_fp = lp2; /* Link in */ + lp2->l_fp = lp1; + lp1->l_bp = lp2; + lp2->l_bp = lp3; + for (i = 0; i < n; ++i) + lp2->l_text[i] = c; + curwp->w_dotp = lp2; + curwp->w_doto = n; + return (TRUE); + } + doto = curwp->w_doto; /* Save for later */ + if (lp1->l_used + n > lp1->l_size) + { /* Hard: reallocate */ + if ((lp2 = lalloc(lp1->l_used + n)) == NULL) + return (FALSE); + cp1 = &lp1->l_text[0]; + cp2 = &lp2->l_text[0]; + while (cp1 != &lp1->l_text[doto]) + *cp2++ = *cp1++; + cp2 += n; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + lp1->l_bp->l_fp = lp2; + lp2->l_fp = lp1->l_fp; + lp1->l_fp->l_bp = lp2; + lp2->l_bp = lp1->l_bp; + free((char *) lp1); + } + else + { /* Easy: in place */ + lp2 = lp1; /* Pretend new line */ + lp2->l_used += n; + cp2 = &lp1->l_text[lp1->l_used]; + cp1 = cp2 - n; + while (cp1 != &lp1->l_text[doto]) + *--cp2 = *--cp1; + } + for (i = 0; i < n; ++i) /* Add the characters */ + lp2->l_text[doto + i] = c; + wp = wheadp; /* Update windows */ + while (wp != NULL) + { + if (wp->w_linep == lp1) + wp->w_linep = lp2; + if (wp->w_dotp == lp1) + { + wp->w_dotp = lp2; + if (wp == curwp || wp->w_doto > doto) + wp->w_doto += n; + } + if (wp->w_markp == lp1) + { + wp->w_markp = lp2; + if (wp->w_marko > doto) + wp->w_marko += n; + } + wp = wp->w_wndp; + } + return (TRUE); +} + +/* + * Insert a newline into the buffer at the current location of dot in the + * current window. The funny ass-backwards way it does things is not a botch; + * it just makes the last line in the file not a special case. Return TRUE if + * everything works out and FALSE on error (memory allocation failure). The + * update of dot and mark is a bit easier then in the above case, because the + * split forces more updating. + */ +int lnewline() +{ + WINDOW *wp; + char *cp1, *cp2; + LINE *lp1, *lp2; + int doto; + + lchange(WFHARD); + + curwp->w_bufp->b_lines++; + + lp1 = curwp->w_dotp; /* Get the address and */ + doto = curwp->w_doto; /* offset of "." */ + if ((lp2 = lalloc(doto)) == NULL) /* New first half line */ + return (FALSE); + cp1 = &lp1->l_text[0]; /* Shuffle text around */ + cp2 = &lp2->l_text[0]; + while (cp1 != &lp1->l_text[doto]) + *cp2++ = *cp1++; + cp2 = &lp1->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + lp1->l_used -= doto; + lp2->l_bp = lp1->l_bp; + lp1->l_bp = lp2; + lp2->l_bp->l_fp = lp2; + lp2->l_fp = lp1; + wp = wheadp; /* Windows */ + while (wp != NULL) + { + if (wp->w_linep == lp1) + wp->w_linep = lp2; + if (wp->w_dotp == lp1) + { + if (wp->w_doto < doto) + wp->w_dotp = lp2; + else + wp->w_doto -= doto; + } + if (wp->w_markp == lp1) + { + if (wp->w_marko < doto) + wp->w_markp = lp2; + else + wp->w_marko -= doto; + } + wp = wp->w_wndp; + } + curwp->w_dotline++; + return (TRUE); +} + +/* + * This function deletes "n" bytes, starting at dot. It understands how do + * deal with end of lines, etc. It returns TRUE if all of the characters were + * deleted, and FALSE if they were not (because dot ran into the end of the + * buffer. The "kflag" is TRUE if the text should be put in the kill buffer. + */ +int ldelete(int n, int kflag) +{ + LINE *dotp; + WINDOW *wp; + char *cp1, *cp2; + int doto, chunk; + + while (n != 0) + { + dotp = curwp->w_dotp; + doto = curwp->w_doto; + if (dotp == curbp->b_linep) /* Hit end of buffer */ + return (FALSE); + chunk = dotp->l_used - doto; /* Size of chunk */ + if (chunk > n) + chunk = n; + if (chunk == 0) + { /* End of line, merge */ + lchange(WFHARD); + if (ldelnewline() == FALSE + || (kflag != FALSE && kinsert('\n') == FALSE)) + return (FALSE); + --n; + continue; + } + lchange(WFEDIT); + cp1 = &dotp->l_text[doto]; /* Scrunch text */ + cp2 = cp1 + chunk; + if (kflag != FALSE) + { /* Kill? */ + while (cp1 != cp2) + { + if (kinsert (*cp1) == FALSE) + return (FALSE); + ++cp1; + } + cp1 = &dotp->l_text[doto]; + } + while (cp2 != &dotp->l_text[dotp->l_used]) + *cp1++ = *cp2++; + dotp->l_used -= chunk; + wp = wheadp; /* Fix windows */ + while (wp != NULL) + { + if (wp->w_dotp == dotp && wp->w_doto >= doto) + { + wp->w_doto -= chunk; + if (wp->w_doto < doto) + wp->w_doto = doto; + } + if (wp->w_markp == dotp && wp->w_marko >= doto) + { + wp->w_marko -= chunk; + if (wp->w_marko < doto) + wp->w_marko = doto; + } + wp = wp->w_wndp; + } + n -= chunk; + } + return (TRUE); +} + +/* + * Delete a newline. Join the current line with the next line. If the next + * line is the magic header line always return TRUE; merging the last line + * with the header line can be thought of as always being a successful + * operation, even if nothing is done, and this makes the kill buffer work + * "right". Easy cases can be done by shuffling data around. Hard cases + * require that lines be moved about in memory. Return FALSE on error and TRUE + * if all looks ok. Called by "ldelete" only. + */ +int ldelnewline() +{ + LINE *lp1, *lp2, *lp3; + WINDOW *wp; + char *cp1, *cp2; + + lp1 = curwp->w_dotp; + lp2 = lp1->l_fp; + if (lp2 == curbp->b_linep) + { /* At the buffer end */ + if (lp1->l_used == 0) /* Blank line */ + lfree(lp1); + return (TRUE); + } + /* Keep line counts in sync */ + curwp->w_bufp->b_lines--; + if (lp2->l_used <= lp1->l_size - lp1->l_used) + { + cp1 = &lp1->l_text[lp1->l_used]; + cp2 = &lp2->l_text[0]; + while (cp2 != &lp2->l_text[lp2->l_used]) + *cp1++ = *cp2++; + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp2) + wp->w_linep = lp1; + if (wp->w_dotp == lp2) + { + wp->w_dotp = lp1; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp2) + { + wp->w_markp = lp1; + wp->w_marko += lp1->l_used; + } + wp = wp->w_wndp; + } + lp1->l_used += lp2->l_used; + lp1->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp1; + free((char *) lp2); + return (TRUE); + } + if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL) + return (FALSE); + cp1 = &lp1->l_text[0]; + cp2 = &lp3->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + cp1 = &lp2->l_text[0]; + while (cp1 != &lp2->l_text[lp2->l_used]) + *cp2++ = *cp1++; + lp1->l_bp->l_fp = lp3; + lp3->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp3; + lp3->l_bp = lp1->l_bp; + wp = wheadp; + while (wp != NULL) + { + if (wp->w_linep == lp1 || wp->w_linep == lp2) + wp->w_linep = lp3; + if (wp->w_dotp == lp1) + wp->w_dotp = lp3; + else if (wp->w_dotp == lp2) + { + wp->w_dotp = lp3; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp1) + wp->w_markp = lp3; + else if (wp->w_markp == lp2) + { + wp->w_markp = lp3; + wp->w_marko += lp1->l_used; + } + wp = wp->w_wndp; + } + free((char *) lp1); + free((char *) lp2); + return (TRUE); +} + +/* + * Delete all of the text saved in the kill buffer. Called by commands when a + * new kill context is being created. The kill buffer array is released, just + * in case the buffer has grown to immense size. No errors. + */ +void kdelete() +{ + if (kbufp != NULL) + { + free((char *) kbufp); + kbufp = NULL; + kused = 0; + ksize = 0; + } +} + +/* + * Insert a character to the kill buffer, enlarging the buffer if there isn't + * any room. Always grow the buffer in chunks, on the assumption that if you + * put something in the kill buffer you are going to put more stuff there too + * later. Return TRUE if all is well, and FALSE on errors. + */ +int kinsert(int c) +{ + char *nbufp; + + if (kused == ksize) + { + if (ksize == 0) /* first time through? */ + nbufp = malloc(KBLOCK); /* alloc the first block */ + else /* or re allocate a bigger block */ + nbufp = realloc(kbufp, ksize + KBLOCK); + if (nbufp == NULL) /* abort if it fails */ + return (FALSE); + kbufp = nbufp; /* point our global at it */ + ksize += KBLOCK; /* and adjust the size */ + } + kbufp[kused++] = c; + return (TRUE); +} + +/* + * This function gets characters from the kill buffer. If the character index + * "n" is off the end, it returns "-1". This lets the caller just scan along + * until it gets a "-1" back. + */ +int kremove(int n) +{ + if (n >= kused) + return (-1); + else + return (kbufp[n] & 0xFF); +} diff --git a/src/cmd/emg/main.c b/src/cmd/emg/main.c new file mode 100644 index 0000000..880c410 --- /dev/null +++ b/src/cmd/emg/main.c @@ -0,0 +1,465 @@ +/* This file is in the public domain. */ + +/* + * This program is in public domain; originally written by Dave G. Conroy. + * This file contains the main driving routine, and some keyboard processing + * code + */ + +#define maindef /* make global definitions not external */ + +#include /* strncpy(3) */ +#include /* malloc(3) */ +#include "estruct.h" /* global structures and defines */ +#include "efunc.h" /* function declarations and name table */ +#include "edef.h" /* global definitions */ +#include "ebind.h" + +extern void getwinsize(); +extern void vtinit(); +extern void vttidy(); +extern void update(); +extern void mlerase(); +extern void mlwrite(); +extern int mlyesno(char *prompt); +extern void makename(char bname[], char fname[]); +extern int readin(char fname[]); +extern int linsert(int f, int n); +extern int anycb(); +extern BUFFER *bfind(); + +void edinit(char bname[]); +int execute(int c, int f, int n); +int getkey(); +int getctl(); +int quickexit(int f, int n); +int quit(int f, int n); +int ctlxlp(int f, int n); +int ctlxrp(int f, int n); +int ctlxe(int f, int n); +int ctrlg(int f, int n); +int extendedcmd(int f, int n); + +int main(int argc, char *argv[]) +{ + BUFFER *bp; + char bname[NBUFN]; /* buffer name of file to read */ + int c, f, n, mflag; + int ffile; /* first file flag */ + int carg; /* current arg to scan */ + int basec; /* c stripped of meta character */ + + /* initialize the editor and process the startup file */ + getwinsize(); /* find out the "real" screen size */ + strncpy(bname, "main", 5); /* default buffer name */ + edinit(bname); /* Buffers, windows */ + vtinit(); /* Displays */ + ffile = TRUE; /* no file to edit yet */ + update(); /* let the user know we are here */ + + /* scan through the command line and get the files to edit */ + for (carg = 1; carg < argc; ++carg) + { + /* set up a buffer for this file */ + makename(bname, argv[carg]); + + /* if this is the first file, read it in */ + if (ffile) + { + bp = curbp; + makename(bname, argv[carg]); + strncpy(bp->b_bname, bname, NBUFN); + strncpy(bp->b_fname, argv[carg], NFILEN); + if (readin(argv[carg]) == ABORT) + { + strncpy(bp->b_bname, "main", 5); + strncpy(bp->b_fname, "", 1); + } + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; + ffile = FALSE; + } + else + { + /* set this to inactive */ + bp = bfind(bname, TRUE, 0); + strncpy(bp->b_fname, argv[carg], NFILEN); + bp->b_active = FALSE; + } + } + + /* setup to process commands */ + lastflag = 0; /* Fake last flags */ + curwp->w_flag |= WFMODE; /* and force an update */ + + loop: + update(); /* Fix up the screen */ + c = getkey(); + if (mpresf != FALSE) + { + mlerase(); + update(); + } + f = FALSE; + n = 1; + + /* do META-# processing if needed */ + + basec = c & ~META; /* strip meta char off if there */ + if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) + { + f = TRUE; /* there is a # arg */ + n = 0; /* start with a zero default */ + mflag = 1; /* current minus flag */ + c = basec; /* strip the META */ + while ((c >= '0' && c <= '9') || (c == '-')) + { + if (c == '-') + { + /* already hit a minus or digit? */ + if ((mflag == -1) || (n != 0)) + break; + mflag = -1; + } + else + n = n * 10 + (c - '0'); + if ((n == 0) && (mflag == -1)) /* lonely - */ + mlwrite("Arg:"); + else + mlwrite("Arg: %d", n * mflag); + + c = getkey(); /* get the next key */ + } + n = n * mflag; /* figure in the sign */ + } + /* do ^U repeat argument processing */ + + if (c == (CTRL | 'U')) + { /* ^U, start argument */ + f = TRUE; + n = 4; /* with argument of 4 */ + mflag = 0; /* that can be discarded */ + mlwrite("Arg: 4"); + while (((c = getkey ()) >= '0') + && ((c <= '9') || (c == (CTRL | 'U')) || (c == '-'))) + { + if (c == (CTRL | 'U')) + n = n * 4; + /* + * If dash, and start of argument string, set arg. + * to -1. Otherwise, insert it. + */ + else if (c == '-') + { + if (mflag) + break; + n = 0; + mflag = -1; + } + /* + * If first digit entered, replace previous argument + * with digit and set sign. Otherwise, append to arg. + */ + else + { + if (!mflag) + { + n = 0; + mflag = 1; + } + n = 10 * n + c - '0'; + } + mlwrite("Arg: %d", (mflag >= 0) ? n : (n ? -n : -1)); + } + /* + * Make arguments preceded by a minus sign negative and change + * the special argument "^U -" to an effective "^U -1". + */ + if (mflag == -1) + { + if (n == 0) + n++; + n = -n; + } + } + + if (c == (CTRL | 'X')) /* ^X is a prefix */ + c = CTLX | getctl (); + if (kbdmip != NULL) + { /* Save macro strokes */ + if (c != (CTLX | ')') && kbdmip > &kbdm[NKBDM - 6]) + { + ctrlg(FALSE, 0); + goto loop; + } + if (f != FALSE) + { + *kbdmip++ = (CTRL | 'U'); + *kbdmip++ = n; + } + *kbdmip++ = c; + } + execute(c, f, n); /* Do it */ + goto loop; +} + +/* + * Initialize all of the buffers and windows. The buffer name is passed down + * as an argument, because the main routine may have been told to read in a + * file by default, and we want the buffer name to be right. + */ +void edinit(char bname[]) +{ + BUFFER *bp; + WINDOW *wp; + + bp = bfind(bname, TRUE, 0); /* First buffer */ + blistp = bfind("[List]", TRUE, BFTEMP); /* Buffer list buffer */ + wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ + if (bp == NULL || wp == NULL || blistp == NULL) + exit (1); + curbp = bp; /* Make this current */ + wheadp = wp; + curwp = wp; + wp->w_wndp = NULL; /* Initialize window */ + wp->w_bufp = bp; + bp->b_nwnd = 1; /* Displayed */ + wp->w_linep = bp->b_linep; + wp->w_dotp = bp->b_linep; + wp->w_doto = 0; + wp->w_markp = NULL; + wp->w_marko = 0; + wp->w_toprow = 0; + wp->w_ntrows = term.t_nrow - 1; /* "-1" for mode line */ + wp->w_force = 0; + wp->w_flag = WFMODE | WFHARD; /* Full */ +} + +/* + * This is the general command execution routine. It handles the fake binding + * of all the keys to "self-insert". It also clears out the "thisflag" word, + * and arranges to move it to the "lastflag", so that the next command can + * look at it. Return the status of command. + */ +int execute(int c, int f, int n) +{ + KEYTAB *ktp; + int status; + + ktp = &keytab[0]; /* Look in key table */ + while (ktp->k_fp != NULL) + { + if (ktp->k_code == c) + { + thisflag = 0; + status = (*ktp->k_fp) (f, n); + lastflag = thisflag; + return (status); + } + ++ktp; + } + + if ((c >= 0x20 && c <= 0x7E) /* Self inserting */ + || (c >= 0xA0 && c <= 0xFE)) + { + if (n <= 0) + { /* Fenceposts */ + lastflag = 0; + return (n < 0 ? FALSE : TRUE); + } + thisflag = 0; /* For the future */ + + status = linsert(n, c); + + lastflag = thisflag; + return (status); + } + mlwrite("\007[Key not bound]"); /* complain */ + lastflag = 0; /* Fake last flags */ + return (FALSE); +} + +/* + * Read in a key. Do the standard keyboard preprocessing. Convert the keys to + * the internal character set. + */ +int getkey() +{ + int c; + + c = (*term.t_getchar) (); + + if (c == METACH) + { /* Apply M- prefix */ + c = getctl (); + return (META | c); + } + if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */ + c = CTRL | (c + '@'); + return (c); +} + +/* + * Get a key. Apply control modifications to the read key. + */ +int getctl() +{ + int c; + + c = (*term.t_getchar) (); + if (c >= 'a' && c <= 'z') /* Force to upper */ + c -= 0x20; + if (c >= 0x00 && c <= 0x1F) /* C0 control -> C- */ + c = CTRL | (c + '@'); + return (c); +} + +/* + * Fancy quit command, as implemented by Norm. If any buffer has changed + * do a write on that buffer and exit emacs, otherwise simply exit. + */ +int quickexit(int f, int n) +{ + BUFFER *bp; /* scanning pointer to buffers */ + + bp = bheadp; + while (bp != NULL) + { + if ((bp->b_flag & BFCHG) != 0 /* Changed */ + && (bp->b_flag & BFTEMP) == 0) + { /* Real */ + curbp = bp; /* make that buffer current */ + mlwrite("[Saving %s]", (int*)bp->b_fname); + filesave(f, n); + } + bp = bp->b_bufp; /* on to the next buffer */ + } + return quit(f, n); /* conditionally quit */ +} + +/* + * Quit command. If an argument, always quit. Otherwise confirm if a buffer + * has been changed and not written out. Normally bound to "C-X C-C". + */ +int quit(int f, int n) +{ + int s; + + if (f != FALSE /* Argument forces it */ + || anycb () == FALSE /* All buffers clean */ + || (s = mlyesno("Modified buffers exist. Leave anyway")) == TRUE) + { + vttidy(); + exit (0); + } + mlwrite(""); + return (s); +} + +/* + * Begin a keyboard macro. Error if not at the top level in keyboard + * processing. Set up variables and return. + */ +int ctlxlp(int f, int n) +{ + if (kbdmip != NULL || kbdmop != NULL) + { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[Start macro]"); + kbdmip = &kbdm[0]; + return (TRUE); +} + +/* + * End keyboard macro. Check for the same limit conditions as the above + * routine. Set up the variables and return to the caller. + */ +int ctlxrp(int f, int n) +{ + if (kbdmip == NULL) + { + mlwrite("Not now"); + return (FALSE); + } + mlwrite("[End macro]"); + kbdmip = NULL; + return (TRUE); +} + +/* + * Execute a macro. The command argument is the number of times to loop. Quit + * as soon as a command gets an error. Return TRUE if all ok, else FALSE. + */ +int ctlxe(int f, int n) +{ + int c, af, an, s; + + if (kbdmip != NULL || kbdmop != NULL) + { + mlwrite("No macro defined"); + return (FALSE); + } + if (n <= 0) + return (TRUE); + do + { + kbdmop = &kbdm[0]; + do + { + af = FALSE; + an = 1; + if ((c = *kbdmop++) == (CTRL | 'U')) + { + af = TRUE; + an = *kbdmop++; + c = *kbdmop++; + } + s = TRUE; + } + while (c != (CTLX | ')') && (s = execute(c, af, an)) == TRUE); + kbdmop = NULL; + } + while (s == TRUE && --n); + return (s); +} + +/* + * Abort. Beep the beeper. Kill off any keyboard macro, etc., that is in + * progress. Sometimes called as a routine, to do general aborting of stuff. + */ +int ctrlg(int f, int n) +{ + (*term.t_beep) (); + if (kbdmip != NULL) + { + kbdm[0] = (CTLX | ')'); + kbdmip = NULL; + } + mlwrite("[Aborted]"); + return (ABORT); +} + +/* + * Handle ANSI escape-extended commands (with "ESC [" or "ESC O" prefix) + */ +int extendedcmd(int f, int n) +{ + int (*cmd)(); + int c; + + c = getctl(); + switch (c) + { + case 'A': cmd = backline; break; + case 'B': cmd = forwline; break; + case 'C': cmd = forwchar; break; + case 'D': cmd = backchar; break; + case 'H': cmd = gotobob; break; + case 'W': cmd = gotoeob; break; + default: mlwrite("\007[Key not bound]"); + return (FALSE); + } + return cmd(f, n); +} diff --git a/src/cmd/emg/random.c b/src/cmd/emg/random.c new file mode 100644 index 0000000..39e48c8 --- /dev/null +++ b/src/cmd/emg/random.c @@ -0,0 +1,290 @@ +/* This file is in the public domain. */ + +/* + * This file contains the command processing functions for a number of random + * commands. There is no functional grouping here, for sure. + */ + +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern void lchange(int flag); +extern int lnewline(); +extern int linsert(int n, int c); +extern int backchar(int f, int n); +extern void kdelete(); +extern int ldelete(int f, int n); +extern int kremove(int k); + +int setfillcol(int f, int n); +int getccol(int bflg); +int twiddle(int f, int n); +int quote(int f, int n); +int tab(int f, int n); +int openline(int f, int n); +int newline(int f, int n); +int forwdel(int f, int n); +int backdel(int f, int n); +int killtext(int f, int n); +int yank(int f, int n); + +/* + * Set fill column to n. + */ +int setfillcol(int f, int n) +{ + fillcol = n; + mlwrite("[Fill column is %d]", n); + return (TRUE); +} + +/* + * Return current column. Stop at first non-blank given TRUE argument. + */ +int getccol(int bflg) +{ + int c, i, col; + + col = 0; + for (i = 0; i < curwp->w_doto; ++i) + { + c = lgetc(curwp->w_dotp, i); + if (c != ' ' && c != '\t' && bflg) + break; + if (c == '\t') + col |= 0x07; + else if (c < 0x20 || c == 0x7F) + ++col; + ++col; + } + return (col); +} + +/* + * Twiddle the two characters on either side of dot. If dot is at the end of + * the line twiddle the two characters before it. Return with an error if dot + * is at the beginning of line; it seems to be a bit pointless to make this + * work. This fixes up a very common typo with a single stroke. Normally bound + * to "C-T". This always works within a line, so "WFEDIT" is good enough + */ +int twiddle(int f, int n) +{ + LINE *dotp; + int doto, cl, cr; + + dotp = curwp->w_dotp; + doto = curwp->w_doto; + if (doto == llength(dotp) && --doto < 0) + return (FALSE); + cr = lgetc(dotp, doto); + if (--doto < 0) + return (FALSE); + cl = lgetc(dotp, doto); + lputc(dotp, doto + 0, cr); + lputc(dotp, doto + 1, cl); + lchange(WFEDIT); + return (TRUE); +} + +/* + * Quote the next character, and insert it into the buffer. All the characters + * are taken literally, with the exception of the newline, which always has + * its line splitting meaning. The character is always read, even if it is + * inserted 0 times, for regularity. Bound to "C-Q" + */ +int quote(int f, int n) +{ + int s, c; + + c = (*term.t_getchar) (); + if (n < 0) + return (FALSE); + if (n == 0) + return (TRUE); + if (c == '\n') + { + do + { + s = lnewline(); + } + while (s == TRUE && --n); + return (s); + } + return (linsert(n, c)); +} + +/* + * Insert a tab into file. + * Bound to "C-I" + */ +int tab(int f, int n) +{ + if (n < 0) + return (FALSE); + return (linsert(n, 9)); +} + +/* + * Open up some blank space. The basic plan is to insert a bunch of newlines, + * and then back up over them. Everything is done by the subcommand + * processors. They even handle the looping. Normally this is bound to "C-O" + */ +int openline(int f, int n) +{ + int i, s; + + if (n < 0) + return (FALSE); + if (n == 0) + return (TRUE); + i = n; /* Insert newlines */ + do + { + s = lnewline(); + } + while (s == TRUE && --i); + if (s == TRUE) /* Then back up overtop */ + s = backchar(f, n); /* of them all */ + return (s); +} + +/* + * Insert a newline. Bound to "C-M". + */ +int newline(int f, int n) +{ + int s; + + if (n < 0) + return (FALSE); + + /* insert some lines */ + while (n--) + { + if ((s = lnewline()) != TRUE) + return (s); + } + return (TRUE); +} + +/* + * Delete forward. This is real easy, because the basic delete routine does + * all of the work. Watches for negative arguments, and does the right thing. + * If any argument is present, it kills rather than deletes, to prevent loss + * of text if typed with a big argument. Normally bound to "C-D" + */ +int forwdel(int f, int n) +{ + if (n < 0) + return (backdel(f, -n)); + if (f != FALSE) + { /* Really a kill */ + if ((lastflag & CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + } + return (ldelete(n, f)); +} + +/* + * Delete backwards. This is quite easy too, because it's all done with other + * functions. Just move the cursor back, and delete forwards. Like delete + * forward, this actually does a kill if presented with an argument. Bound to + * both "RUBOUT" and "C-H" + */ +int backdel(int f, int n) +{ + int s; + + if (n < 0) + return (forwdel(f, -n)); + if (f != FALSE) + { /* Really a kill */ + if ((lastflag & CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + } + if ((s = backchar(f, n)) == TRUE) + s = ldelete(n, f); + return (s); +} + +/* + * Kill text. If called without an argument, it kills from dot to the end of + * the line, unless it is at the end of the line, when it kills the newline. + * If called with an argument of 0, it kills from the start of the line to + * dot. If called with a positive argument, it kills from dot forward over + * that number of newlines. If called with a negative argument it kills + * backwards that number of newlines. Normally bound to "C-K" + */ +int killtext(int f, int n) +{ + LINE *nextp; + int chunk; + + if ((lastflag & CFKILL) == 0)/* Clear kill buffer if last wasn't a kill */ + kdelete(); + thisflag |= CFKILL; + if (f == FALSE) + { + chunk = llength(curwp->w_dotp) - curwp->w_doto; + if (chunk == 0) + chunk = 1; + } + else if (n == 0) + { + chunk = curwp->w_doto; + curwp->w_doto = 0; + } + else if (n > 0) + { + chunk = llength(curwp->w_dotp) - curwp->w_doto + 1; + nextp = lforw(curwp->w_dotp); + while (--n) + { + if (nextp == curbp->b_linep) + return (FALSE); + chunk += llength(nextp) + 1; + nextp = lforw(nextp); + } + } + else + { + mlwrite("neg kill"); + return (FALSE); + } + return (ldelete(chunk, TRUE)); +} + +/* + * Yank text back from the kill buffer. This is really easy. All of the work + * is done by the standard insert routines. All you do is run the loop, and + * check for errors. Bound to "C-Y" + */ +int yank(int f, int n) +{ + int c, i; + + if (n < 0) + return (FALSE); + while (n--) + { + i = 0; + while ((c = kremove(i)) >= 0) + { + if (c == '\n') + { + if (lnewline(FALSE, 1) == FALSE) + return (FALSE); + } + else + { + if (linsert(1, c) == FALSE) + return (FALSE); + } + ++i; + } + } + return (TRUE); +} diff --git a/src/cmd/emg/region.c b/src/cmd/emg/region.c new file mode 100644 index 0000000..1d85d32 --- /dev/null +++ b/src/cmd/emg/region.c @@ -0,0 +1,142 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file deal with the region, that magic space between + * "." and mark. Some functions are commands. Some functions are just for + * internal use + */ + +#include "estruct.h" +#include "edef.h" + +extern void kdelete(); +extern int ldelete(int f, int n); +extern int kinsert(int c); +extern void mlwrite(); + +int killregion(int f, int n); +int copyregion(int f, int n); +int getregion(REGION *rp); + +/* + * Kill the region. Ask "getregion" to figure out the bounds of the region. + * Move "." to the start, and kill the characters. Bound to "C-W" + */ +int killregion(int f, int n) +{ + REGION region; + int s; + + if ((s = getregion(®ion)) != TRUE) + return (s); + if ((lastflag & CFKILL) == 0) /* This is a kill type */ + kdelete(); /* command, so do magic */ + thisflag |= CFKILL; /* kill buffer stuff */ + curwp->w_dotp = region.r_linep; + curwp->w_doto = region.r_offset; + return (ldelete(region.r_size, TRUE)); +} + +/* + * Copy all of the characters in the region to the kill buffer. Don't move dot + * at all. This is a bit like a kill region followed by a yank. Bound to "M-W" + */ +int copyregion(int f, int n) +{ + LINE *linep; + REGION region; + int loffs, s; + + if ((s = getregion(®ion)) != TRUE) + return (s); + if ((lastflag & CFKILL) == 0) /* Kill type command */ + kdelete(); + thisflag |= CFKILL; + linep = region.r_linep; /* Current line */ + loffs = region.r_offset; /* Current offset */ + while (region.r_size--) + { + if (loffs == llength(linep)) + { /* End of line */ + if ((s = kinsert('\n')) != TRUE) + return (s); + linep = lforw(linep); + loffs = 0; + } + else + { /* Middle of line */ + if ((s = kinsert(lgetc(linep, loffs))) != TRUE) + return (s); + ++loffs; + } + } + return (TRUE); +} + +/* + * This routine figures out the bounds of the region in the current window, + * and fills in the fields of the "REGION" structure pointed to by "rp". + * Because the dot and mark are usually very close together, we scan outward + * from dot looking for mark. This should save time. Return a standard code. + * Callers of this routine should be prepared to get an "ABORT" status; we + * might make this have the conform thing later + */ +int getregion(REGION *rp) +{ + LINE *flp, *blp; + int fsize, bsize; + + if (curwp->w_markp == (struct LINE*)0) + { + mlwrite("No mark set in this window"); + return (FALSE); + } + if (curwp->w_dotp == curwp->w_markp) + { + rp->r_linep = curwp->w_dotp; + if (curwp->w_doto < curwp->w_marko) + { + rp->r_offset = curwp->w_doto; + rp->r_size = curwp->w_marko - curwp->w_doto; + } + else + { + rp->r_offset = curwp->w_marko; + rp->r_size = curwp->w_doto - curwp->w_marko; + } + return (TRUE); + } + blp = curwp->w_dotp; + bsize = curwp->w_doto; + flp = curwp->w_dotp; + fsize = llength(flp) - curwp->w_doto + 1; + while (flp != curbp->b_linep || lback(blp) != curbp->b_linep) + { + if (flp != curbp->b_linep) + { + flp = lforw(flp); + if (flp == curwp->w_markp) + { + rp->r_linep = curwp->w_dotp; + rp->r_offset = curwp->w_doto; + rp->r_size = fsize + curwp->w_marko; + return (TRUE); + } + fsize += llength(flp) + 1; + } + if (lback(blp) != curbp->b_linep) + { + blp = lback(blp); + bsize += llength(blp) + 1; + if (blp == curwp->w_markp) + { + rp->r_linep = blp; + rp->r_offset = curwp->w_marko; + rp->r_size = bsize - curwp->w_marko; + return (TRUE); + } + } + } + mlwrite("Bug: lost mark"); + return (FALSE); +} diff --git a/src/cmd/emg/search.c b/src/cmd/emg/search.c new file mode 100644 index 0000000..8eafae8 --- /dev/null +++ b/src/cmd/emg/search.c @@ -0,0 +1,535 @@ +/* This file is in the public domain. */ + +/* + * The functions in this file implement commands that search in the forward + * and backward directions. There are no special characters in the search + * strings + */ + +#include /* strncpy(3), strncat(3) */ +#include "estruct.h" +#include "edef.h" + +extern void mlwrite(); +extern int mlreplyt(char *prompt, char *buf, int nbuf, char eolchar); +extern void update(); +extern int forwchar(int f, int n); +extern int ldelete(int n, int kflag); +extern int lnewline(); +extern int linsert(int n, int c); + +int forwsearch(int f, int n); +int forwhunt(int f, int n); +int backsearch(int f, int n); +int backhunt(int f, int n); +int bsearch(int f, int n); +int eq(int bc, int pc); +int readpattern(char *prompt); +int sreplace(int f, int n); +int qreplace(int f, int n); +int replaces(int kind, int f, int n); +int forscan(char *patrn, int leavep); +void expandp(char *srcstr, char *deststr, int maxlength); + +#define PTBEG 1 /* leave the point at the begining on search */ +#define PTEND 2 /* leave the point at the end on search */ + +/* + * Search forward. Get a search string from the user, and search, beginning at + * ".", for the string. If found, reset the "." to be just after the match + * string, and [perhaps] repaint the display. Bound to "C-S" + */ +int forwsearch(int f, int n) +{ + int status; + + if (n == 0) /* resolve the repeat count */ + n = 1; + if (n < 1) /* search backwards */ + return (backsearch(f, -n)); + + /* ask the user for the text of a pattern */ + if ((status = readpattern("Search")) != TRUE) + return (status); + + /* search for the pattern */ + while (n-- > 0) + { + if ((status = forscan(&pat[0], PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) + mlwrite("Not found"); + return (status); +} + +int forwhunt(int f, int n) +{ + int status = 0; + + /* resolve the repeat count */ + if (n == 0) + n = 1; + if (n < 1) /* search backwards */ + return (backhunt(f, -n)); + + /* Make sure a pattern exists */ + if (pat[0] == 0) + { + mlwrite("No pattern set"); + return (FALSE); + } + /* search for the pattern */ + while (n-- > 0) + { + if ((status = forscan(&pat[0], PTEND)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE) + mlwrite("Not found"); + return (status); +} + +/* + * Reverse search. Get a search string from the user, and search, starting at + * "." and proceeding toward the front of the buffer. If found "." is left + * pointing at the first character of the pattern [the last character that was + * matched]. Bound to "C-R" + */ +int backsearch(int f, int n) +{ + int s; + + if (n == 0) /* resolve null and negative arguments */ + n = 1; + if (n < 1) + return (forwsearch(f, -n)); + + if ((s = readpattern("Reverse search")) != TRUE) /* get a pattern to search */ + return (s); + + return bsearch(f, n); /* and go search for it */ +} + +/* hunt backward for the last search string entered + */ +int backhunt(int f, int n) +{ + if (n == 0) /* resolve null and negative arguments */ + n = 1; + if (n < 1) + return (forwhunt(f, -n)); + + if (pat[0] == 0) /* Make sure a pattern exists */ + { + mlwrite("No pattern set"); + return (FALSE); + } + return bsearch(f, n); /* go search */ +} + +int bsearch(int f, int n) +{ + LINE *clp, *tlp; + char *epp, *pp; + int cbo, tbo, c; + + /* find a pointer to the end of the pattern */ + for (epp = &pat[0]; epp[1] != 0; ++epp) + ; + + /* make local copies of the starting location */ + clp = curwp->w_dotp; + cbo = curwp->w_doto; + + while (n-- > 0) + { + for (;;) + { + /* if we are at the begining of the line, wrap back around */ + if (cbo == 0) + { + clp = lback(clp); + + if (clp == curbp->b_linep) + { + mlwrite("Not found"); + return (FALSE); + } + cbo = llength(clp) + 1; + } + /* fake the at the end of a line */ + if (--cbo == llength(clp)) + c = '\n'; + else + c = lgetc(clp, cbo); + + /* check for a match against the end of the pattern */ + if (eq(c, *epp) != FALSE) + { + tlp = clp; + tbo = cbo; + pp = epp; + /* scanning backwards through the rest of the pattern + * looking for a match */ + while (pp != &pat[0]) + { + /* wrap across a line break */ + if (tbo == 0) + { + tlp = lback(tlp); + if (tlp == curbp->b_linep) + goto fail; + + tbo = llength(tlp) + 1; + } + /* fake the */ + if (--tbo == llength(tlp)) + c = '\n'; + else + c = lgetc(tlp, tbo); + + if (eq(c, *--pp) == FALSE) + goto fail; + } + + /* A Match! reset the current cursor */ + curwp->w_dotp = tlp; + curwp->w_doto = tbo; + curwp->w_flag |= WFMOVE; + goto next; + } + fail:; + } + next:; + } + return (TRUE); +} + +/* + * Compare two characters. The "bc" comes from the buffer. It has it's case + * folded out. The "pc" is from the pattern + */ +int eq(int bc, int pc) +{ + if (bc >= 'a' && bc <= 'z') + bc -= 0x20; + if (pc >= 'a' && pc <= 'z') + pc -= 0x20; + if (bc == pc) + return (TRUE); + return (FALSE); +} + +/* + * Read a pattern. Stash it in the external variable "pat". The "pat" is not + * updated if the user types in an empty line. If the user typed an empty + * line, and there is no old pattern, it is an error. Display the old pattern, + * in the style of Jeff Lomicka. There is some do-it-yourself control + * expansion. + */ +int readpattern(char *prompt) +{ + char tpat[NPAT + 20]; + int s; + + strncpy(tpat, prompt, NPAT-12); /* copy prompt to output string */ + strncat(tpat, " [", 3); /* build new prompt string */ + expandp(&pat[0], &tpat[strlen (tpat)], NPAT / 2); /* add old pattern */ + strncat(tpat, "]: ", 4); + + s = mlreplyt(tpat, tpat, NPAT, 10); /* Read pattern */ + + if (s == TRUE) /* Specified */ + strncpy(pat, tpat, NPAT); + else if (s == FALSE && pat[0] != 0) /* CR, but old one */ + s = TRUE; + + return (s); +} + +/* + * Search and replace (ESC-R) + */ +int sreplace(int f, int n) +{ + return (replaces(FALSE, f, n)); +} + +/* + * search and replace with query (ESC-CTRL-R) + */ +int qreplace(int f, int n) +{ + return (replaces(TRUE, f, n)); +} + +/* + * replaces: search for a string and replace it with another string. query + * might be enabled (according to kind) + */ +int replaces(int kind, int f, int n) +{ + LINE *origline; /* original "." position */ + char tmpc; /* temporary character */ + char c; /* input char for query */ + char tpat[NPAT]; /* temporary to hold search pattern */ + int i; /* loop index */ + int s; /* success flag on pattern inputs */ + int slength, rlength; /* length of search and replace strings */ + int numsub; /* number of substitutions */ + int nummatch; /* number of found matches */ + int nlflag; /* last char of search string a ? */ + int nlrepl; /* was a replace done on the last line? */ + int origoff; /* and offset (for . query option) */ + + /* check for negative repititions */ + if (f && n < 0) + return (FALSE); + + /* ask the user for the text of a pattern */ + if ((s = readpattern((kind == FALSE ? "Replace" : "Query replace"))) != TRUE) + return (s); + strncpy(&tpat[0], &pat[0], NPAT); /* salt it away */ + + /* ask for the replacement string */ + strncpy(&pat[0], &rpat[0], NPAT); /* set up default string */ + if ((s = readpattern("with")) == ABORT) + return (s); + + /* move everything to the right place and length them */ + strncpy(&rpat[0], &pat[0], NPAT); + strncpy(&pat[0], &tpat[0], NPAT); + slength = strlen(&pat[0]); + rlength = strlen(&rpat[0]); + + /* set up flags so we can make sure not to do a recursive replace on the + * last line */ + nlflag = (pat[slength - 1] == '\n'); + nlrepl = FALSE; + + /* build query replace question string */ + strncpy(tpat, "Replace '", 10); + expandp(&pat[0], &tpat[strlen (tpat)], NPAT / 3); + strncat(tpat, "' with '", 9); + + expandp(&rpat[0], &tpat[strlen (tpat)], NPAT / 3); + strncat(tpat, "'? ", 4); + + /* save original . position */ + origline = curwp->w_dotp; + origoff = curwp->w_doto; + + /* scan through the file */ + numsub = 0; + nummatch = 0; + while ((f == FALSE || n > nummatch) && + (nlflag == FALSE || nlrepl == FALSE)) + { + /* search for the pattern */ + if (forscan(&pat[0], PTBEG) != TRUE) + break; /* all done */ + ++nummatch; /* increment # of matches */ + + /* check if we are on the last line */ + nlrepl = (lforw (curwp->w_dotp) == curwp->w_bufp->b_linep); + + /* check for query */ + if (kind) + { + /* get the query */ + mlwrite(&tpat[0], &pat[0], &rpat[0]); + qprompt: + update(); /* show the proposed place to change */ + c = (*term.t_getchar) (); /* and input */ + mlwrite(""); /* and clear it */ + + /* and respond appropriately */ + switch (c) + { + case 'y': /* yes, substitute */ + case ' ': + break; + + case 'n': /* no, onword */ + forwchar(FALSE, 1); + continue; + + case '!': /* yes/stop asking */ + kind = FALSE; + break; + + case '.': /* abort! and return */ + /* restore old position */ + curwp->w_dotp = origline; + curwp->w_doto = origoff; + curwp->w_flag |= WFMOVE; + + case BELL: /* abort! and stay */ + mlwrite("Aborted!"); + return (FALSE); + + case 0x0d: /* controlled exit */ + case 'q': + return (TRUE); + + default: /* bitch and beep */ + (*term.t_beep) (); + + case '?': /* help me */ + mlwrite("(Y)es, (N)o, (!)Do the rest, (^G,RET,q)Abort, (.)Abort back, (?)Help: "); + goto qprompt; + } + } + /* delete the sucker */ + if (ldelete(slength, FALSE) != TRUE) + { + /* error while deleting */ + mlwrite("ERROR while deleting"); + return (FALSE); + } + /* and insert its replacement */ + for (i = 0; i < rlength; i++) + { + tmpc = rpat[i]; + s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc)); + if (s != TRUE) + { + /* error while inserting */ + mlwrite("Out of memory while inserting"); + return (FALSE); + } + } + + numsub++; /* increment # of substitutions */ + } + + /* and report the results */ + mlwrite("%d substitutions", numsub); + return (TRUE); +} + +/* search forward for a + */ +int forscan(char *patrn, int leavep) +{ + LINE *curline; /* current line during scan */ + LINE *lastline; /* last line position during scan */ + LINE *matchline; /* current line during matching */ + char *patptr; /* pointer into pattern */ + int curoff; /* position within current line */ + int lastoff; /* position within last line */ + int c; /* character at current position */ + int matchoff; /* position in matching line */ + + /* setup local scan pointers to global "." */ + curline = curwp->w_dotp; + curoff = curwp->w_doto; + + /* scan each character until we hit the head link record */ + while (curline != curbp->b_linep) + { + /* save the current position in case we need to restore it on a match */ + lastline = curline; + lastoff = curoff; + + /* get the current character resolving EOLs */ + if (curoff == llength(curline)) + { /* if at EOL */ + curline = lforw(curline); /* skip to next line */ + curoff = 0; + c = '\n'; /* and return a */ + } + else + c = lgetc(curline, curoff++); /* get the char */ + + /* test it against first char in pattern */ + if (eq(c, patrn[0]) != FALSE) /* if we find it. */ + { + /* setup match pointers */ + matchline = curline; + matchoff = curoff; + patptr = &patrn[0]; + + /* scan through patrn for a match */ + while (*++patptr != 0) + { + /* advance all the pointers */ + if (matchoff == llength(matchline)) + { + /* advance past EOL */ + matchline = lforw(matchline); + matchoff = 0; + c = '\n'; + } + else + c = lgetc(matchline, matchoff++); + + /* and test it against the pattern */ + if (eq(*patptr, c) == FALSE) + goto fail; + } + + /* A SUCCESSFULL MATCH!!! */ + /* reset the global "." pointers */ + if (leavep == PTEND) + { /* at end of string */ + curwp->w_dotp = matchline; + curwp->w_doto = matchoff; + } + else + { /* at begining of string */ + curwp->w_dotp = lastline; + curwp->w_doto = lastoff; + } + curwp->w_flag |= WFMOVE; /* flag that we have moved */ + return (TRUE); + } + fail:; /* continue to search */ + } + /* we could not find a match */ + return (FALSE); +} + +/* expandp: expand control key sequences for output + */ +void expandp(char *srcstr, char *deststr, int maxlength) +{ + char c; /* current char to translate */ + + /* scan through the string */ + while ((c = *srcstr++) != 0) + { + if (c < 0x20 || c == 0x7f) + { /* control character */ + *deststr++ = '^'; + *deststr++ = c ^ 0x40; + maxlength -= 2; + } + else if (c == '%') + { + *deststr++ = '%'; + *deststr++ = '%'; + maxlength -= 2; + } + else + { /* any other character */ + *deststr++ = c; + maxlength--; + } + + /* check for maxlength */ + if (maxlength < 4) + { + *deststr++ = '$'; + *deststr = '\0'; + return; + } + } + *deststr = '\0'; + return; +} diff --git a/src/cmd/emg/tcap.c b/src/cmd/emg/tcap.c new file mode 100644 index 0000000..3bf4ef6 --- /dev/null +++ b/src/cmd/emg/tcap.c @@ -0,0 +1,144 @@ +/* This file is in the public domain. */ + +/* termios video driver */ + +#define termdef 1 /* don't define "term" externally */ + +/* Did you remember to set FORCE_COLS? */ +#ifndef FORCE_COLS +#define FORCE_COLS 80 +#endif + +/* Did you remember to set FORCE_ROWS? */ +#ifndef FORCE_ROWS +#define FORCE_ROWS 24 +#endif + +/* + * XXX: + * Default/sane(?) maximum column and row sizes. + * Taken from mg1a. + * + * Let the user override this with a + * CFLAGS += -DMAXCOL=XXX -DMAXROW=XXX + * line in the Makefile. + */ +#ifndef MAXCOL +#define MAXCOL 132 +#endif + +#ifndef MAXROW +#define MAXROW 66 +#endif + +#include /* puts(3), snprintf(3) */ +#include "estruct.h" +#include "edef.h" +#undef CTRL /* Needs to be done here. */ +#include + +extern int tgetent(); +extern char *tgetstr(); +extern char *tgoto(); +extern void tputs(); + +extern char *getenv(); +extern void ttopen(); +extern int ttgetc(); +extern void ttputc(); +extern void ttflush(); +extern void ttclose(); + +extern void panic(); + +void getwinsize(); +void tcapopen(); +void tcapmove(int row, int col); +void tcapeeol(); +void tcapeeop(); +void tcaprev(); +void tcapbeep(); + +#define MARGIN 8 +#define SCRSIZ 64 +#define BEL 0x07 +#define TCAPSLEN 64 + +char tcapbuf[TCAPSLEN]; /* capabilities actually used */ +char *CM, *CE, *CL, *SO, *SE; + +TERM term = { + 0, 0, MARGIN, SCRSIZ, tcapopen, ttclose, ttgetc, ttputc, + ttflush, tcapmove, tcapeeol, tcapeeop, tcapbeep, tcaprev +}; + +void getwinsize() +{ + int cols = FORCE_COLS; + int rows = FORCE_ROWS; + + /* Too small and we're out */ + if ((cols < 10) || (rows < 3)) + panic("Too few columns or rows"); + + if (FORCE_COLS > MAXCOL) + cols = MAXCOL; + if (FORCE_ROWS > MAXROW) + rows = MAXROW; + + term.t_ncol = cols; + term.t_nrow = rows - 1; +} + +void tcapopen() +{ + char tcbuf[1024]; + char *p, *tv_stype; + + if ((tv_stype = getenv("TERM")) == NULL) + panic("TERM not defined"); + if ((tgetent(tcbuf, tv_stype)) != 1) + panic("Unknown terminal type"); + p = tcapbuf; + CL = tgetstr("cl", &p); + CM = tgetstr("cm", &p); + CE = tgetstr("ce", &p); + SE = tgetstr("se", &p); + SO = tgetstr("so", &p); + + if (CE == NULL) + eolexist = FALSE; + if (SO != NULL && SE != NULL) + revexist = TRUE; + if (CL == NULL || CM == NULL) + panic("Need cl & cm abilities"); + if (p >= &tcapbuf[TCAPSLEN]) /* XXX */ + panic("Description too big"); + ttopen (); +} + +void tcaprev(int state) +{ + if (revexist) + tputs((state ? SO : SE), 1, ttputc); +} + +void tcapmove (int row, int col) +{ + tputs(tgoto(CM, col, row), 1, ttputc); +} + +void tcapeeol() +{ + tputs(CE, 1, ttputc); +} + +void tcapeeop() +{ + tputs(CL, 1, ttputc); +} + +void tcapbeep() +{ + ttputc(BEL); +} diff --git a/src/cmd/emg/ttyio.c b/src/cmd/emg/ttyio.c new file mode 100644 index 0000000..f94e26e --- /dev/null +++ b/src/cmd/emg/ttyio.c @@ -0,0 +1,163 @@ +/* This file is in the public domain. */ + +/* + * This file comes from mg1a. + * Uses the panic function from OpenBSD's mg. + */ + +/* + * Ultrix-32 and Unix terminal I/O. + * The functions in this file + * negotiate with the operating system for + * keyboard characters, and write characters to + * the display in a barely buffered fashion. + */ + +#include +#include +#include +#include +#include +#undef CTRL +#include "estruct.h" + +void ttflush(void); +void panic(char *); + +extern void getwinsize(); + +#define NROW 66 /* Rows. */ +#define NCOL 132 /* Columns. */ +#define NOBUF 512 /* Output buffer size. */ + +char obuf[NOBUF]; /* Output buffer. */ +int nobuf; +struct sgttyb oldtty; /* V6/V7 stty data. */ +struct sgttyb newtty; +struct tchars oldtchars; /* V7 editing. */ +struct tchars newtchars; +struct ltchars oldltchars; /* 4.2 BSD editing. */ +struct ltchars newltchars; + +/* + * This function gets called once, to set up + * the terminal channel. + */ +void ttopen(void) { + register char *tv_stype; + char *getenv(), *tgetstr(), tcbuf[1024]; + + if (ioctl(0, TIOCGETP, (char *) &oldtty) < 0) + panic("ttopen can't get sgtty"); + newtty.sg_ospeed = oldtty.sg_ospeed; + newtty.sg_ispeed = oldtty.sg_ispeed; + newtty.sg_erase = oldtty.sg_erase; + newtty.sg_kill = oldtty.sg_kill; + newtty.sg_flags = oldtty.sg_flags; + newtty.sg_flags &= ~(ECHO|CRMOD); /* Kill echo, CR=>NL. */ + newtty.sg_flags |= RAW|ANYP; /* raw mode for 8 bit path.*/ + if (ioctl(0, TIOCSETP, (char *) &newtty) < 0) + panic("ttopen can't set sgtty"); + if (ioctl(0, TIOCGETC, (char *) &oldtchars) < 0) + panic("ttopen can't get chars"); + newtchars.t_intrc = 0xFF; /* Interrupt. */ + newtchars.t_quitc = 0xFF; /* Quit. */ + newtchars.t_startc = 0xFF; /* ^Q, for terminal. */ + newtchars.t_stopc = 0xFF; /* ^S, for terminal. */ + newtchars.t_eofc = 0xFF; + newtchars.t_brkc = 0xFF; + if (ioctl(0, TIOCSETC, (char *) &newtchars) < 0) + panic("ttopen can't set chars"); + if (ioctl(0, TIOCGLTC, (char *) &oldltchars) < 0) + panic("ttopen can't get ltchars"); + newltchars.t_suspc = 0xFF; /* Suspend #1. */ + newltchars.t_dsuspc = 0xFF; /* Suspend #2. */ + newltchars.t_rprntc = 0xFF; + newltchars.t_flushc = 0xFF; /* Output flush. */ + newltchars.t_werasc = 0xFF; + newltchars.t_lnextc = 0xFF; /* Literal next. */ + if (ioctl(0, TIOCSLTC, (char *) &newltchars) < 0) + panic("ttopen can't set ltchars"); + +/* do this the REAL way */ + if ((tv_stype = getenv("TERM")) == NULL) + panic("TERM not defined"); + + if((tgetent(tcbuf, tv_stype)) != 1) + panic("Unknown terminal type"); + + getwinsize(); +} + +/* + * This function gets called just + * before we go back home to the shell. Put all of + * the terminal parameters back. + */ +void ttclose(void) { + ttflush(); + if (ioctl(0, TIOCSLTC, (char *) &oldltchars) < 0) + panic("ttclose can't set ltchars"); + if (ioctl(0, TIOCSETC, (char *) &oldtchars) < 0) + panic("ttclose can't set chars"); + if (ioctl(0, TIOCSETP, (char *) &oldtty) < 0) + panic("ttclose can't set sgtty"); +} + +/* + * Write character to the display. + * Characters are buffered up, to make things + * a little bit more efficient. + */ +int ttputc(int c) { + if (nobuf >= NOBUF) + ttflush(); + obuf[nobuf++] = c; + return (c); +} + +/* + * Flush output. + */ +void ttflush(void) { + if (nobuf != 0) { + if (write(1, obuf, nobuf) != nobuf) + panic("ttflush write failed"); + nobuf = 0; + } +} + +/* + * Read character from terminal. + * All 8 bits are returned, so that you can use + * a multi-national terminal. + */ +int ttgetc(void) { + char buf[1]; + + while (read(0, &buf[0], 1) != 1); + return (buf[0] & 0xFF); +} + +/* + * typeahead returns TRUE if there are characters available to be read + * in. + */ +int typeahead(void) { + int x; + + return((ioctl(0, FIONREAD, (char *) &x) < 0) ? 0 : x); +} + +/* + * panic - just exit, as quickly as we can. + * From OpenBSD's mg. + */ +void panic(char *s) +{ + ttclose(); + (void) fputs("panic: ", stderr); + (void) fputs(s, stderr); + (void) fputc('\n', stderr); + exit(1); +} diff --git a/src/cmd/emg/window.c b/src/cmd/emg/window.c new file mode 100644 index 0000000..a1e6947 --- /dev/null +++ b/src/cmd/emg/window.c @@ -0,0 +1,336 @@ +/* This file is in the public domain. */ + +/* + * Window management. Some of the functions are internal, and some are + * attached to keys that the user actually types + */ + +#include /* free(3), malloc(3) */ +#include "estruct.h" +#include "edef.h" + +extern void upmode(); +extern void mlwrite(); + +int refresh(int f, int n); +int nextwind(int f, int n); +int prevwind(int f, int n); +int onlywind(int f, int n); +int splitwind(int f, int n); +int enlargewind(int f, int n); +int shrinkwind(int f, int n); +WINDOW* wpopup(); + +/* + * Refresh the screen. With no argument, it does the refresh and centers + * the cursor on the screen. With an argument it does a reposition instead. + * Bound to "C-L" + */ +int refresh(int f, int n) +{ + if (n >= 0) + n++; /* adjust to screen row */ + if (f == FALSE) + { + sgarbf = TRUE; + n = 0; /* Center dot */ + } + curwp->w_force = n; + curwp->w_flag |= WFFORCE; + return (TRUE); +} + +/* + * The command make the next window (next => down the screen) the current + * window. There are no real errors, although the command does nothing if + * there is only 1 window on the screen. Bound to "C-X C-N" + */ +int nextwind(int f, int n) +{ + WINDOW *wp; + + if ((wp = curwp->w_wndp) == NULL) + wp = wheadp; + + curwp = wp; + curbp = wp->w_bufp; + upmode(); + return (TRUE); +} + +/* + * This command makes the previous window (previous => up the screen) the + * current window. There arn't any errors, although the command does not do a + * lot if there is 1 window + */ +int prevwind(int f, int n) +{ + WINDOW *wp1, *wp2; + + wp1 = wheadp; + wp2 = curwp; + + if (wp1 == wp2) + wp2 = NULL; + + while (wp1->w_wndp != wp2) + wp1 = wp1->w_wndp; + + curwp = wp1; + curbp = wp1->w_bufp; + upmode(); + return (TRUE); +} + +/* + * This command makes the current window the only window on the screen. Bound + * to "C-X 1". Try to set the framing so that "." does not have to move on the + * display. Some care has to be taken to keep the values of dot and mark in + * the buffer structures right if the distruction of a window makes a buffer + * become undisplayed + */ +int onlywind(int f, int n) +{ + WINDOW *wp; + LINE *lp; + int i; + + while (wheadp != curwp) + { + wp = wheadp; + wheadp = wp->w_wndp; + if (--wp->w_bufp->b_nwnd == 0) + { + wp->w_bufp->b_dotp = wp->w_dotp; + wp->w_bufp->b_doto = wp->w_doto; + wp->w_bufp->b_markp = wp->w_markp; + wp->w_bufp->b_marko = wp->w_marko; + } + free((char *) wp); + } + while (curwp->w_wndp != NULL) + { + wp = curwp->w_wndp; + curwp->w_wndp = wp->w_wndp; + if (--wp->w_bufp->b_nwnd == 0) + { + wp->w_bufp->b_dotp = wp->w_dotp; + wp->w_bufp->b_doto = wp->w_doto; + wp->w_bufp->b_markp = wp->w_markp; + wp->w_bufp->b_marko = wp->w_marko; + } + free((char *) wp); + } + lp = curwp->w_linep; + i = curwp->w_toprow; + while (i != 0 && lback (lp) != curbp->b_linep) + { + --i; + lp = lback(lp); + } + curwp->w_toprow = 0; + curwp->w_ntrows = term.t_nrow - 1; + curwp->w_linep = lp; + curwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Split the current window. A window smaller than 3 lines cannot be split. + * The only other error that is possible is a "malloc" failure allocating the + * structure for the new window. Bound to "C-X 2" + */ +int splitwind(int f, int n) +{ + LINE *lp; + WINDOW *wp, *wp1, *wp2; + int ntru, ntrl, ntrd; + + if (curwp->w_ntrows < 3) + { + mlwrite("Cannot split a %d line window", curwp->w_ntrows); + return (FALSE); + } + if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) + { + mlwrite("Cannot allocate WINDOW block"); + return (FALSE); + } + ++curbp->b_nwnd; /* Displayed twice */ + wp->w_bufp = curbp; + wp->w_dotp = curwp->w_dotp; + wp->w_doto = curwp->w_doto; + wp->w_markp = curwp->w_markp; + wp->w_marko = curwp->w_marko; + wp->w_flag = 0; + wp->w_force = 0; + ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */ + ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */ + lp = curwp->w_linep; + ntrd = 0; + while (lp != curwp->w_dotp) + { + ++ntrd; + lp = lforw(lp); + } + lp = curwp->w_linep; + if (ntrd <= ntru) + { /* Old is upper window */ + if (ntrd == ntru) /* Hit mode line */ + lp = lforw(lp); + curwp->w_ntrows = ntru; + wp->w_wndp = curwp->w_wndp; + curwp->w_wndp = wp; + wp->w_toprow = curwp->w_toprow + ntru + 1; + wp->w_ntrows = ntrl; + } + else + { /* Old is lower window */ + wp1 = NULL; + wp2 = wheadp; + while (wp2 != curwp) + { + wp1 = wp2; + wp2 = wp2->w_wndp; + } + if (wp1 == NULL) + wheadp = wp; + else + wp1->w_wndp = wp; + wp->w_wndp = curwp; + wp->w_toprow = curwp->w_toprow; + wp->w_ntrows = ntru; + ++ntru; /* Mode line */ + curwp->w_toprow += ntru; + curwp->w_ntrows = ntrl; + while (ntru--) + lp = lforw (lp); + } + curwp->w_linep = lp; /* Adjust the top lines */ + wp->w_linep = lp; /* if necessary */ + curwp->w_flag |= WFMODE | WFHARD; + wp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Enlarge the current window. Find the window that loses space. Make sure it + * is big enough. If so, hack the window descriptions, and ask redisplay to do + * all the hard work. You don't just set "force reframe" because dot would + * move. Bound to "C-X Z" + */ +int enlargewind(int f, int n) +{ + WINDOW *adjwp; + LINE *lp; + int i; + + if (n < 0) + return (shrinkwind(f, -n)); + if (wheadp->w_wndp == NULL) + { + mlwrite("Only one window"); + return (FALSE); + } + if ((adjwp = curwp->w_wndp) == NULL) + { + adjwp = wheadp; + while (adjwp->w_wndp != curwp) + adjwp = adjwp->w_wndp; + } + if (adjwp->w_ntrows <= n) + { + mlwrite("Impossible change"); + return (FALSE); + } + if (curwp->w_wndp == adjwp) + { /* Shrink below */ + lp = adjwp->w_linep; + for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i) + lp = lforw(lp); + adjwp->w_linep = lp; + adjwp->w_toprow += n; + } + else + { /* Shrink above */ + lp = curwp->w_linep; + for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i) + lp = lback(lp); + curwp->w_linep = lp; + curwp->w_toprow -= n; + } + curwp->w_ntrows += n; + adjwp->w_ntrows -= n; + curwp->w_flag |= WFMODE | WFHARD; + adjwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Shrink the current window. Find the window that gains space. Hack at the + * window descriptions. Ask the redisplay to do all the hard work + */ +int shrinkwind(int f, int n) +{ + WINDOW *adjwp; + LINE *lp; + int i; + + if (n < 0) + return (enlargewind(f, -n)); + if (wheadp->w_wndp == NULL) + { + mlwrite("Only one window"); + return (FALSE); + } + if ((adjwp = curwp->w_wndp) == NULL) + { + adjwp = wheadp; + while (adjwp->w_wndp != curwp) + adjwp = adjwp->w_wndp; + } + if (curwp->w_ntrows <= n) + { + mlwrite("Impossible change"); + return (FALSE); + } + if (curwp->w_wndp == adjwp) + { /* Grow below */ + lp = adjwp->w_linep; + for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i) + lp = lback(lp); + adjwp->w_linep = lp; + adjwp->w_toprow -= n; + } + else + { /* Grow above */ + lp = curwp->w_linep; + for (i = 0; i < n && lp != curbp->b_linep; ++i) + lp = lforw(lp); + curwp->w_linep = lp; + curwp->w_toprow += n; + } + curwp->w_ntrows -= n; + adjwp->w_ntrows += n; + curwp->w_flag |= WFMODE | WFHARD; + adjwp->w_flag |= WFMODE | WFHARD; + return (TRUE); +} + +/* + * Pick a window for a pop-up. Split the screen if there is only one window. + * Pick the uppermost window that isn't the current window. An LRU algorithm + * might be better. Return a pointer, or NULL on error + */ +WINDOW* wpopup() +{ + WINDOW *wp; + + if (wheadp->w_wndp == NULL /* Only 1 window */ + && splitwind(FALSE, 0) == FALSE) /* and it won't split */ + return (NULL); + wp = wheadp; /* Find window to use */ + while (wp != NULL && wp == curwp) + wp = wp->w_wndp; + return (wp); +} diff --git a/src/cmd/emg/word.c b/src/cmd/emg/word.c new file mode 100644 index 0000000..abdc058 --- /dev/null +++ b/src/cmd/emg/word.c @@ -0,0 +1,284 @@ +/* This file is in the public domain. */ + +/* + * The routines in this file implement commands that work word at a time. + * There are all sorts of word mode commands. If I do any sentence and/or + * paragraph mode commands, they are likely to be put in this file + */ + +#include "estruct.h" +#include "edef.h" + +extern int backchar(int f, int n); +extern int forwchar(int f, int n); +extern void lchange(int flag); +extern int ldelete(int n, int kflag); +extern void mlwrite(); +extern int linsert(int n, int c); +extern int lnewline(); + +int backword(int f, int n); +int forwword(int f, int n); +int upperword(int f, int n); +int lowerword(int f, int n); +int capword(int f, int n); +int delfword(int f, int n); +int delbword(int f, int n); +int inword(); + +/* + * Move the cursor backward by "n" words. All of the details of motion are + * performed by the "backchar" and "forwchar" routines. Error if you try to + * move beyond the buffers + */ +int backword(int f, int n) +{ + if (n < 0) + return (forwword(f, -n)); + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + while (n--) + { + while (inword() == FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (forwchar(FALSE, 1)); +} + +/* + * Move the cursor forward by the specified number of words. All of the motion + * is done by "forwchar". Error if you try and move beyond the buffer's end + */ +int forwword(int f, int n) +{ + if (n < 0) + return (backword(f, -n)); + while (n--) + { + while (inword() != FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move, + * convert any characters to upper case. Error if you try and move beyond the + * end of the buffer. Bound to "M-U" + */ +int upperword(int f, int n) +{ + int c; + + if (n < 0) + return (FALSE); + while (n--) + { + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) + { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'a' && c <= 'z') + { + c -= 'a' - 'A'; + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert characters to lower case. Error if you try and move over the end of + * the buffer. Bound to "M-L" + */ +int lowerword(int f, int n) +{ + int c; + + if (n < 0) + return (FALSE); + while (n--) + { + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) + { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'A' && c <= 'Z') + { + c += 'a' - 'A'; + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert the first character of the word to upper case, and subsequent + * characters to lower case. Error if you try and move past the end of the + * buffer. Bound to "M-C" + */ +int capword(int f, int n) +{ + int c; + + if (n < 0) + return(FALSE); + while (n--) + { + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + if (inword() != FALSE) + { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'a' && c <= 'z') + { + c -= 'a' - 'A'; + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + while (inword() != FALSE) + { + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'A' && c <= 'Z') + { + c += 'a' - 'A'; + lputc(curwp->w_dotp, curwp->w_doto, c); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + } + return (TRUE); +} + +/* + * Kill forward by "n" words. Remember the location of dot. Move forward by + * the right number of words. Put dot back where it was and issue the kill + * command for the right number of characters. Bound to "M-D" + */ +int delfword(int f, int n) +{ + LINE *dotp; + int size, doto; + + if (n < 0) + return (FALSE); + dotp = curwp->w_dotp; + doto = curwp->w_doto; + size = 0; + while (n--) + { + while (inword() != FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + while (inword() == FALSE) + { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + } + curwp->w_dotp = dotp; + curwp->w_doto = doto; + return (ldelete(size, TRUE)); +} + +/* + * Kill backwards by "n" words. Move backwards by the desired number of words, + * counting the characters. When dot is finally moved to its resting place, + * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace" + */ +int delbword(int f, int n) +{ + int size; + + if (n < 0) + return (FALSE); + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + size = 0; + while (n--) + { + while (inword() == FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + while (inword() != FALSE) + { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + return (ldelete(size, TRUE)); +} + +/* + * Return TRUE if the character at dot is a character that is considered to be + * part of a word. The word character list is hard coded. Should be setable + */ +int inword() +{ + int c; + + if (curwp->w_doto == llength(curwp->w_dotp)) + return (FALSE); + c = lgetc(curwp->w_dotp, curwp->w_doto); + if (c >= 'a' && c <= 'z') + return (TRUE); + if (c >= 'A' && c <= 'Z') + return (TRUE); + if (c >= '0' && c <= '9') + return (TRUE); + if (c == '$' || c == '_') /* For identifiers */ + return (TRUE); + return (FALSE); +} From bbba8d6f954305a465e85fc9298a9edd69538b4e Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Sun, 25 May 2014 16:25:15 -0400 Subject: [PATCH 09/40] Remove all hardcoded make commands, changing them to ${MAKE}. This is a first step towards being able to build RetroBSD on *BSD. --- src/cmd/smux/Makefile | 10 +++++----- src/cmd/tip/Makefile | 8 ++++---- src/cmd/uucp/Makefile | 4 ++-- src/games/Makefile | 4 ++-- src/libc/Makefile | 6 +++--- src/libc/mips/Makefile | 8 ++++---- src/libtermlib/Makefile | 2 +- src/share/Makefile | 6 +++--- sys/pic32/Makefile | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/cmd/smux/Makefile b/src/cmd/smux/Makefile index 24ba798..1adc829 100644 --- a/src/cmd/smux/Makefile +++ b/src/cmd/smux/Makefile @@ -1,10 +1,10 @@ all: - make -C retro - make -C linux + ${MAKE} -C retro + ${MAKE} -C linux install: - make -C retro install + ${MAKE} -C retro install clean: - make -C retro clean - make -C linux clean + ${MAKE} -C retro clean + ${MAKE} -C linux clean diff --git a/src/cmd/tip/Makefile b/src/cmd/tip/Makefile index bbccde6..ff6cde3 100644 --- a/src/cmd/tip/Makefile +++ b/src/cmd/tip/Makefile @@ -68,18 +68,18 @@ acutab.o: acutab.c log.o remote.o: Makefile aculib: FRC - cd aculib; make ${MFLAGS} + cd aculib; ${MAKE} ${MFLAGS} clean: FRC rm -f ${OBJS} core tip tip.elf tip.dis - cd aculib; make ${MFLAGS} clean + cd aculib; ${MAKE} ${MFLAGS} clean depend: FRC mkdep ${CFLAGS} ${SRCS} - cd aculib; make ${MFLAGS} depend + cd aculib; ${MAKE} ${MFLAGS} depend install: aculib tip - cd aculib; make ${MFLAGS} install + cd aculib; ${MAKE} ${MFLAGS} install cp tip ${DESTDIR}/bin/tip rm -f ${DESTDIR}/bin/cu touch ${DESTDIR}/${ADM}/aculog diff --git a/src/cmd/uucp/Makefile b/src/cmd/uucp/Makefile index 3923691..fde7bb8 100644 --- a/src/cmd/uucp/Makefile +++ b/src/cmd/uucp/Makefile @@ -44,7 +44,7 @@ SUBDIRS=C. D.${HOSTNAME}X D.${HOSTNAME} D. X. TM. all: libacu $(ALL) libacu: - cd aculib && make + cd aculib && ${MAKE} uuencode: uuencode.o @@ -136,7 +136,7 @@ install: uuencode uuencode clean: rm -f *.o $(ALL) libuucp.a *.dis *.elf - cd aculib; make ${MFLAGS} clean + cd aculib; ${MAKE} ${MFLAGS} clean depend: mkdep ${CFLAGS} *.c diff --git a/src/games/Makefile b/src/games/Makefile index e20f0dc..62d2ae2 100644 --- a/src/games/Makefile +++ b/src/games/Makefile @@ -42,7 +42,7 @@ FRC: install: $(STD) $(NSTD) -for i in $(SUBDIR); do \ - make -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) install; done + ${MAKE} -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) install; done -for i in $(STD) $(NSTD); do \ install $$i $(DESTDIR)/games/$$i; done -for i in *.6; do \ @@ -52,7 +52,7 @@ install: $(STD) $(NSTD) clean: rm -f a.out core *.s *.o *.dis *.elf $(STD) $(NSTD) - -for i in $(SUBDIR); do make -C $$i $(MFLAGS) clean; done + -for i in $(SUBDIR); do ${MAKE} -C $$i $(MFLAGS) clean; done # Files listed in $(NSTD) have explicit make lines given below. diff --git a/src/libc/Makefile b/src/libc/Makefile index 3d0c081..44cf99f 100644 --- a/src/libc/Makefile +++ b/src/libc/Makefile @@ -40,7 +40,7 @@ all: ../libc.a rm -rf tmp ${ALL}: FRC - cd $@; make ${MFLAGS} DEFS="${DEFS}" + cd $@; ${MAKE} ${MFLAGS} DEFS="${DEFS}" FRC: @@ -51,9 +51,9 @@ install: ../libc.a clean: for i in ${ALL}; \ - do (cd $$i; make ${MFLAGS} clean); done + do (cd $$i; ${MAKE} ${MFLAGS} clean); done rm -rf tmp *.a *~ depend: for i in ${ALL}; \ - do (cd $$i; make ${MFLAGS} DEFS="${DEFS}" depend); done + do (cd $$i; ${MAKE} ${MFLAGS} DEFS="${DEFS}" depend); done diff --git a/src/libc/mips/Makefile b/src/libc/mips/Makefile index 87fb931..a62fcda 100644 --- a/src/libc/mips/Makefile +++ b/src/libc/mips/Makefile @@ -17,19 +17,19 @@ mips.a: ${ALL} rm -rf tmp ${ALL}: FRC - cd $@; make ${MFLAGS} DEFS=${DEFS} + cd $@; ${MAKE} ${MFLAGS} DEFS=${DEFS} FRC: tags: for i in ${ALL}; do \ - (cd $$i; make ${MFLAGS} TAGSFILE=../${TAGSFILE} tags); \ + (cd $$i; ${MAKE} ${MFLAGS} TAGSFILE=../${TAGSFILE} tags); \ done clean: - for i in ${ALL}; do (cd $$i; make ${MFLAGS} clean); done + for i in ${ALL}; do (cd $$i; ${MAKE} ${MFLAGS} clean); done rm -rf *.a tmp *~ depend: for i in ${ALL}; do \ - (cd $$i; make ${MFLAGS} DEFS=${DEFS} depend); done + (cd $$i; ${MAKE} ${MFLAGS} DEFS=${DEFS} depend); done diff --git a/src/libtermlib/Makefile b/src/libtermlib/Makefile index 386f77b..5614e26 100644 --- a/src/libtermlib/Makefile +++ b/src/libtermlib/Makefile @@ -26,7 +26,7 @@ all: ../libtermcap.a termcap .PHONY: termcap termcap: - cd termcap && make + cd termcap && ${MAKE} ../libtermcap.a: ${OBJS} $(AR) cr ../libtermcap.a ${OBJS} diff --git a/src/share/Makefile b/src/share/Makefile index bd0a113..34ce823 100644 --- a/src/share/Makefile +++ b/src/share/Makefile @@ -11,14 +11,14 @@ SUBDIR = misc all: ${SUBDIR} ${SUBDIR}: FRC - cd $@; make ${MFLAGS} + cd $@; ${MAKE} ${MFLAGS} FRC: install: FRC -for i in ${SUBDIR}; do \ - (cd $$i; make ${MFLAGS} DESTDIR=${DESTDIR} install); done + (cd $$i; ${MAKE} ${MFLAGS} DESTDIR=${DESTDIR} install); done clean: rm -f *~ - for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} clean); done + for i in ${SUBDIR}; do (cd $$i; ${MAKE} ${MFLAGS} clean); done diff --git a/sys/pic32/Makefile b/sys/pic32/Makefile index 193371e..e82501f 100644 --- a/sys/pic32/Makefile +++ b/sys/pic32/Makefile @@ -10,12 +10,12 @@ SUBDIR = baremetal dip duinomite duinomite-uart duinomite-e \ default: all: - -for i in $(SUBDIR); do make -C $$i all; done + -for i in $(SUBDIR); do ${MAKE} -C $$i all; done install: clean: - -for i in $(SUBDIR); do make -C $$i clean; done + -for i in $(SUBDIR); do ${MAKE} -C $$i clean; done find .. -name \*~ | xargs rm -f reconfig: From 87489937bf54ad888c4b3cbca108dfbdaf59d53c Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 29 May 2014 14:31:58 -0400 Subject: [PATCH 10/40] Add PgUp and PgDn scrolling to emg, release this as emg 1.6 Make sure emg.keys is installed. --- Makefile | 3 ++- src/cmd/emg/ChangeLog | 5 +++++ src/cmd/emg/README | 11 ++++------- src/cmd/emg/basic.c | 24 ++++++++++++++++++++++++ src/cmd/emg/display.c | 6 +++--- src/cmd/emg/ebind.h | 2 ++ src/cmd/emg/efunc.h | 2 ++ src/cmd/emg/emg.keys | 3 ++- src/cmd/emg/main.c | 4 ++++ 9 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 125ec2d..030221d 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ INC_FILES = $(wildcard include/*.h) \ $(wildcard include/smallc/*.h) \ $(wildcard include/smallc/sys/*.h) \ $(wildcard include/arpa/*.h) -SHARE_FILES = share/re.help share/example/Makefile \ +SHARE_FILES = share/re.help share/emg.keys share/example/Makefile \ share/example/ashello.S share/example/chello.c \ share/example/blkjack.bas share/example/hilow.bas \ share/example/stars.bas share/example/prime.scm \ @@ -179,6 +179,7 @@ cleanall: clean rm -f games/lib/adventure.dat rm -f games/lib/cfscores rm -f share/re.help + rm -f share/emg.keys rm -f share/misc/more.help rm -f etc/termcap etc/remote etc/phones rm -rf share/unixbench diff --git a/src/cmd/emg/ChangeLog b/src/cmd/emg/ChangeLog index 9c41af6..c5d10c8 100644 --- a/src/cmd/emg/ChangeLog +++ b/src/cmd/emg/ChangeLog @@ -1,6 +1,11 @@ ChangeLog ========= +May 29, 2014 : emg 1.6 +---------------------- +emg is now part of the RetroBSD tree. +Add PgUp and PgDn scrolling. + March 16, 2014 : emg 1.5 ------------------------ Add line number to the mode line. diff --git a/src/cmd/emg/README b/src/cmd/emg/README index 1bde8f3..b6e1015 100644 --- a/src/cmd/emg/README +++ b/src/cmd/emg/README @@ -34,11 +34,8 @@ appreciate the history of this software. As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. Versions of emg up to and including 1.2 also supported OpenBSD; OpenBSD -has since dropped the older headers, such as sgtty.h and it is not worth -reimplementing these for OpenBSD, since OpenBSD maintains Mg. +has since dropped the older headers, such as sgtty.h, and it is not worth +reimplementing these for OpenBSD since OpenBSD maintains Mg. -Tarballs can be found here: -http://devio.us/~bcallah/emg/ - -Github repo, for patches: -https://github.com/ibara/emg +==================================== +Brian Callahan diff --git a/src/cmd/emg/basic.c b/src/cmd/emg/basic.c index ca7d30f..75290ea 100644 --- a/src/cmd/emg/basic.c +++ b/src/cmd/emg/basic.c @@ -21,6 +21,8 @@ int forwchar(int f, int n); int backchar(int f, int n); int forwline(int f, int n); int backline(int f, int n); +int pagedown(int f, int n); +int pageup(int f, int n); /* * This routine, given a pointer to a LINE, and the current cursor goal @@ -252,6 +254,28 @@ int backline(int f, int n) return (TRUE); } +/* + * PgDn. Scroll down (FORCE_ROWS - 1). + * Just forwline(f, (FORCE_ROWS -1)) + * Bound to C-V + */ +int pagedown(int f, int n) +{ + forwline(f, (FORCE_ROWS - 1)); + return (TRUE); +} + +/* + * PgUp. Scroll up (FORCE_ROWS - 1). + * Just backline(f, (FORCE_ROWS -1)) + * Bound to M-V + */ +int pageup(int f, int n) +{ + backline(f, (FORCE_ROWS - 1)); + return (TRUE); +} + /* * Set the mark in the current window to the value of "." in the window. No * errors are possible. Bound to "M-.". diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index 721425d..dfe9c0a 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -647,7 +647,7 @@ void modeline(WINDOW *wp) n = 2; /* This is the version string. Do not forget to * increment when releasing a new version. */ - n += vtputs(" emg 1.5 "); + n += vtputs(" emg 1.6 "); vtputc(lchar); vtputc(lchar); @@ -675,8 +675,8 @@ void modeline(WINDOW *wp) n += 3; } - len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", - ((wp->w_dotline +1) / bp->b_lines), + len = snprintf(sl, sizeof(sl), " %ld%% (%d,%d) ", + (long)((100*(wp->w_dotline + 1)) / curwp->w_bufp->b_lines), (wp->w_dotline + 1), getccol(FALSE)); if (len < sizeof(sl) && len != -1) n += vtputs(sl); diff --git a/src/cmd/emg/ebind.h b/src/cmd/emg/ebind.h index a047139..35836dd 100644 --- a/src/cmd/emg/ebind.h +++ b/src/cmd/emg/ebind.h @@ -26,6 +26,7 @@ KEYTAB keytab[] = { {CTRL | 'R', backsearch}, {CTRL | 'S', forwsearch}, {CTRL | 'T', twiddle}, + {CTRL | 'V', pagedown}, {CTRL | 'W', killregion}, {CTRL | 'Y', yank}, {CTLX | '(', ctlxlp}, @@ -63,6 +64,7 @@ KEYTAB keytab[] = { {META | 'R', sreplace}, {META | 'S', forwsearch}, /* non-standard */ {META | 'U', upperword}, + {META | 'V', pageup}, {META | 'W', copyregion}, {META | 'Z', quickexit}, {META | 0x7F, delbword}, diff --git a/src/cmd/emg/efunc.h b/src/cmd/emg/efunc.h index 0531b3c..00bf3ff 100644 --- a/src/cmd/emg/efunc.h +++ b/src/cmd/emg/efunc.h @@ -23,6 +23,8 @@ extern int gotoeol(); /* Move to end of line */ extern int backchar(); /* Move backward by characters */ extern int forwline(); /* Move forward by lines */ extern int backline(); /* Move backward by lines */ +extern int pagedown(); /* PgDn */ +extern int pageup(); /* PgUp */ extern int gotobob(); /* Move to start of buffer */ extern int gotoeob(); /* Move to end of buffer */ extern int setfillcol(); /* Set fill column */ diff --git a/src/cmd/emg/emg.keys b/src/cmd/emg/emg.keys index 6677f1b..9ab44fd 100644 --- a/src/cmd/emg/emg.keys +++ b/src/cmd/emg/emg.keys @@ -1,4 +1,4 @@ - emg keybindings (March 16, 2014) + emg keybindings (May 29, 2014) Based on Ersatz Emacs (2000/09/14) M- means to use the key prior to using another key @@ -13,6 +13,7 @@ M- means to use the key prior to using another key ^P Previous line M-N End of paragraph ^A Front of line M-< or [HOME] Start of file ^E End of line M-> or [END] End of file +^V or [PgDn] Scroll down M-V or [PgUp] Scroll up M-G Go to line Arrow keys are active ------------------------------------------------------------------------------ diff --git a/src/cmd/emg/main.c b/src/cmd/emg/main.c index 880c410..fd48cf1 100644 --- a/src/cmd/emg/main.c +++ b/src/cmd/emg/main.c @@ -458,6 +458,10 @@ int extendedcmd(int f, int n) case 'D': cmd = backchar; break; case 'H': cmd = gotobob; break; case 'W': cmd = gotoeob; break; + case '5': cmd = pageup; getctl(); break; + case '6': cmd = pagedown; getctl(); break; + case '7': cmd = gotobob; getctl(); break; + case '8': cmd = gotoeob; getctl(); break; default: mlwrite("\007[Key not bound]"); return (FALSE); } From dbe51ae2941b609fb24fe5bf99ca25139ab032d7 Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 29 May 2014 15:06:16 -0400 Subject: [PATCH 11/40] This is cleaner, prevent the percent from being greater than 100. --- src/cmd/emg/display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index dfe9c0a..40a9eac 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -623,6 +623,7 @@ void modeline(WINDOW *wp) int lchar; /* character to draw line in buffer with */ int n; /* cursor position count */ int len; /* line/column display check */ + int perc; /* percent down */ char sl[25]; /* line/column display (probably overkill) */ n = wp->w_toprow + wp->w_ntrows; /* Location */ @@ -675,8 +676,11 @@ void modeline(WINDOW *wp) n += 3; } - len = snprintf(sl, sizeof(sl), " %ld%% (%d,%d) ", - (long)((100*(wp->w_dotline + 1)) / curwp->w_bufp->b_lines), + perc = (100*(wp->w_dotline + 1)) / curwp->w_bufp->b_lines; + if (perc > 100) + perc = 100; + + len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", perc, (wp->w_dotline + 1), getccol(FALSE)); if (len < sizeof(sl) && len != -1) n += vtputs(sl); From 29904aacd7e41fe52b9f60b78a8ae3fdd9760d65 Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 29 May 2014 18:03:39 -0400 Subject: [PATCH 12/40] I should trust my instincts. I had this right the first time. --- src/cmd/emg/display.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index 40a9eac..1739aee 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -623,7 +623,6 @@ void modeline(WINDOW *wp) int lchar; /* character to draw line in buffer with */ int n; /* cursor position count */ int len; /* line/column display check */ - int perc; /* percent down */ char sl[25]; /* line/column display (probably overkill) */ n = wp->w_toprow + wp->w_ntrows; /* Location */ @@ -676,11 +675,8 @@ void modeline(WINDOW *wp) n += 3; } - perc = (100*(wp->w_dotline + 1)) / curwp->w_bufp->b_lines; - if (perc > 100) - perc = 100; - - len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", perc, + len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", + ((100*(wp->w_dotline + 1)) / bp->b_lines), (wp->w_dotline + 1), getccol(FALSE)); if (len < sizeof(sl) && len != -1) n += vtputs(sl); From e003436e91ce2f46e73a2ddb718f4c2da4afb195 Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 29 May 2014 18:16:24 -0400 Subject: [PATCH 13/40] Dumbest off-by-one ever... --- src/cmd/emg/display.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index 1739aee..bf54aa2 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -623,6 +623,7 @@ void modeline(WINDOW *wp) int lchar; /* character to draw line in buffer with */ int n; /* cursor position count */ int len; /* line/column display check */ + int perc; /* percent down */ char sl[25]; /* line/column display (probably overkill) */ n = wp->w_toprow + wp->w_ntrows; /* Location */ @@ -676,7 +677,7 @@ void modeline(WINDOW *wp) } len = snprintf(sl, sizeof(sl), " %d%% (%d,%d) ", - ((100*(wp->w_dotline + 1)) / bp->b_lines), + ((100*(wp->w_dotline)) / bp->b_lines), (wp->w_dotline + 1), getccol(FALSE)); if (len < sizeof(sl) && len != -1) n += vtputs(sl); From 04208ea9036a1d5f9856280dc19b368171b27464 Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 29 May 2014 18:20:55 -0400 Subject: [PATCH 14/40] Remove unusued variable... put this down and walk away until tomorrow. --- src/cmd/emg/display.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index bf54aa2..ffc9979 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -623,7 +623,6 @@ void modeline(WINDOW *wp) int lchar; /* character to draw line in buffer with */ int n; /* cursor position count */ int len; /* line/column display check */ - int perc; /* percent down */ char sl[25]; /* line/column display (probably overkill) */ n = wp->w_toprow + wp->w_ntrows; /* Location */ From 5fa78e772b8c302bba24e6b19313281791c412e3 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Wed, 4 Jun 2014 11:46:33 -0700 Subject: [PATCH 15/40] Moved aout sources to separate directory. Fsutil and modff license changed to BSD style. --- src/cmd/Makefile | 2 +- src/cmd/aout/Makefile | 25 +++++++++++++++++++++++++ src/cmd/{as => aout}/aout.c | 0 src/cmd/{as => aout}/mips-dis.c | 0 src/cmd/{as => aout}/mips-opc.c | 0 src/cmd/{as => aout}/mips-opcode.h | 0 src/cmd/{as => aout}/mips16-opc.c | 0 src/cmd/as/Makefile | 25 ++----------------------- src/libc/gen/modff.c | 8 +++----- tools/fsutil/block.c | 20 +++++++++++++++++--- tools/fsutil/bsdfs.h | 20 +++++++++++++++++--- tools/fsutil/check.c | 20 +++++++++++++++++--- tools/fsutil/create.c | 20 +++++++++++++++++--- tools/fsutil/file.c | 20 +++++++++++++++++--- tools/fsutil/fsutil.c | 20 +++++++++++++++++--- tools/fsutil/inode.c | 20 +++++++++++++++++--- tools/fsutil/superblock.c | 20 +++++++++++++++++--- 17 files changed, 167 insertions(+), 53 deletions(-) create mode 100644 src/cmd/aout/Makefile rename src/cmd/{as => aout}/aout.c (100%) rename src/cmd/{as => aout}/mips-dis.c (100%) rename src/cmd/{as => aout}/mips-opc.c (100%) rename src/cmd/{as => aout}/mips-opcode.h (100%) rename src/cmd/{as => aout}/mips16-opc.c (100%) diff --git a/src/cmd/Makefile b/src/cmd/Makefile index f5c7ae2..5d1484f 100644 --- a/src/cmd/Makefile +++ b/src/cmd/Makefile @@ -10,7 +10,7 @@ CFLAGS += -Werror # Programs that live in subdirectories, and have makefiles of their own. # /bin -SUBDIR = adb adc-demo ar as awk basic cc chflags chpass \ +SUBDIR = adb adc-demo aout ar as awk basic cc chflags chpass \ cpp dc diff emg env fdisk find forth fstat glcdtest \ hostname id la lcc lcpp ld ls login make man med \ more nm passwd picoc portio printf pwm \ diff --git a/src/cmd/aout/Makefile b/src/cmd/aout/Makefile new file mode 100644 index 0000000..7ca33a2 --- /dev/null +++ b/src/cmd/aout/Makefile @@ -0,0 +1,25 @@ +# +# aout - Display information from a.out files +# +TOPSRC = $(shell cd ../../..; pwd) +include $(TOPSRC)/target.mk +#include $(TOPSRC)/cross.mk + +CFLAGS += -Werror -Wall -Os +LDFLAGS += + +AOUTOBJS = aout.o mips-dis.o + +all: aout + +aout: $(AOUTOBJS) + ${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS} + ${OBJDUMP} -S aout.elf > aout.dis + ${SIZE} aout.elf + ${ELF2AOUT} aout.elf $@ && rm aout.elf + +clean: + rm -f *.o *.0 *.elf aout tags *~ *.dis + +install: all + install aout $(DESTDIR)/bin/ diff --git a/src/cmd/as/aout.c b/src/cmd/aout/aout.c similarity index 100% rename from src/cmd/as/aout.c rename to src/cmd/aout/aout.c diff --git a/src/cmd/as/mips-dis.c b/src/cmd/aout/mips-dis.c similarity index 100% rename from src/cmd/as/mips-dis.c rename to src/cmd/aout/mips-dis.c diff --git a/src/cmd/as/mips-opc.c b/src/cmd/aout/mips-opc.c similarity index 100% rename from src/cmd/as/mips-opc.c rename to src/cmd/aout/mips-opc.c diff --git a/src/cmd/as/mips-opcode.h b/src/cmd/aout/mips-opcode.h similarity index 100% rename from src/cmd/as/mips-opcode.h rename to src/cmd/aout/mips-opcode.h diff --git a/src/cmd/as/mips16-opc.c b/src/cmd/aout/mips16-opc.c similarity index 100% rename from src/cmd/as/mips16-opc.c rename to src/cmd/aout/mips16-opc.c diff --git a/src/cmd/as/Makefile b/src/cmd/as/Makefile index 78d7e12..06a3019 100644 --- a/src/cmd/as/Makefile +++ b/src/cmd/as/Makefile @@ -1,6 +1,5 @@ # # as - Assembler -# aout - Display information from a.out files # TOPSRC = $(shell cd ../../..; pwd) include $(TOPSRC)/target.mk @@ -9,9 +8,7 @@ include $(TOPSRC)/target.mk CFLAGS += -Werror -Wall -Os LDFLAGS += -AOUTOBJS = aout.o mips-dis.o - -all: as aout +all: as as: as.o ${CC} ${LDFLAGS} -o as.elf as.o ${LIBS} @@ -19,26 +16,8 @@ as: as.o ${SIZE} as.elf ${ELF2AOUT} as.elf $@ && rm as.elf -aout: $(AOUTOBJS) - ${CC} ${LDFLAGS} -o aout.elf $(AOUTOBJS) ${LIBS} - ${OBJDUMP} -S aout.elf > aout.dis - ${SIZE} aout.elf - ${ELF2AOUT} aout.elf $@ && rm aout.elf - clean: - rm -f *.o *.0 *.elf as aout tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o - -test: - /usr/local/pic32-tools/bin/pic32-as -al example.s + rm -f *.o *.0 *.elf as tags *~ *.dis tests/*.dis tests/*.gcc-dis tests/*.o install: all install as $(DESTDIR)/bin/ - install aout $(DESTDIR)/bin/ - -test.dis-gcc: test.s - $(AS) $< -o test.o - ${OBJDUMP} -D test.o > $@ - -test.dis: test.s as aout - ./as $< -o test.o - ./aout test.o > $@ diff --git a/src/libc/gen/modff.c b/src/libc/gen/modff.c index 7eeac60..0595a33 100644 --- a/src/libc/gen/modff.c +++ b/src/libc/gen/modff.c @@ -1,9 +1,9 @@ /* * Written by Serge Vakulenko . * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. */ #include @@ -11,8 +11,6 @@ * modff(float x, float *iptr) * return fraction part of x, and return x's integral part in *iptr. */ -static const float one = 1.0; - float modff (float fx, float *iptr) { union { diff --git a/tools/fsutil/block.c b/tools/fsutil/block.c index d178e66..5aa53ba 100644 --- a/tools/fsutil/block.c +++ b/tools/fsutil/block.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include "bsdfs.h" diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index 4dc8ff9..d27696a 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #define BSDFS_BSIZE 1024 /* block size */ #define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ diff --git a/tools/fsutil/check.c b/tools/fsutil/check.c index cae91b7..6240cde 100644 --- a/tools/fsutil/check.c +++ b/tools/fsutil/check.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include diff --git a/tools/fsutil/create.c b/tools/fsutil/create.c index ad3eea9..28e8b43 100644 --- a/tools/fsutil/create.c +++ b/tools/fsutil/create.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index aed769b..06d5312 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 8f7eca1..03a56f3 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index da70cf5..881df87 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include diff --git a/tools/fsutil/superblock.c b/tools/fsutil/superblock.c index e8c02aa..aa1d373 100644 --- a/tools/fsutil/superblock.c +++ b/tools/fsutil/superblock.c @@ -3,9 +3,23 @@ * * Copyright (C) 2006-2011 Serge Vakulenko, * - * This file is part of RetroBSD project, which is distributed - * under the terms of the GNU General Public License (GPL). - * See the accompanying file "COPYING" for more details. + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. */ #include #include From 70b8d93b21997dcc052ecf1eb56726a2e89c88ab Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Tue, 17 Jun 2014 08:43:13 -0400 Subject: [PATCH 16/40] Update emg man page. --- src/cmd/emg/emg.1 | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/cmd/emg/emg.1 b/src/cmd/emg/emg.1 index f8cea83..b43b026 100644 --- a/src/cmd/emg/emg.1 +++ b/src/cmd/emg/emg.1 @@ -3,7 +3,7 @@ .\" Basic emg man page. .\" As both Ersatz Emacs and Mg are Public Domain, emg is also Public Domain. .\" -.Dd March 23, 2014 +.Dd June 17, 2014 .Os .Dt EMG 1 .Sh NAME @@ -14,12 +14,12 @@ .Op Ar .Sh DESCRIPTION .Nm , -or Ersatz Mg, is an Emacs-like text editor designed for memory-constrained -environments. +or Ersatz Mg, is an Emacs-like text editor designed for RetroBSD +and other memory-constrained environments. .Nm -was originally created to fit into an operating environment of 96K of RAM, and -one in which Mg did not fit and Ersatz Emacs did not build. -By combining parts of each, a working editor was created. +was originally created to fit into an operating environment of 96K of RAM, +and one in which Mg did not fit and Ersatz Emacs did not build. +By combining parts of each a working editor was created. .Pp When invoked without file arguments, .Nm @@ -37,13 +37,17 @@ is also Public Domain. .Sh FILES There is a chart of key bindings in .Pa /usr/local/share/doc/emg/emg.keys . -Consulting this file is a must, as +Consulting this file is a must. +While .Nm -does not guarantee keybindings to be identical to other Emacs implementations. +strives to maintain compatibility with larger Emacs implementations, +there may be features intentionally left unimplemented in order to keep +.Nm +as small as possible. .Sh AUTHORS .Nm -is a combination of Ersatz Emacs and Mg and therefore all authors for both -deserve credit. +is a combination of Ersatz Emacs and Mg and therefore all authors +for both deserve credit. Ersatz Emacs and Mg were combined by .An Brian Callahan Aq Mt bcallah@openbsd.org to create From b6e105c87b5e2096a24a642914dd96d3a209bb2f Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 18 Jun 2014 13:45:24 -0400 Subject: [PATCH 17/40] Fix build after aout reorganization --- lib/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index e821099..49e6364 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -24,8 +24,9 @@ AOUT_OBJS = aout.o mips-dis.o RANLIB_OBJS = ranlib.o archive.o HEADERS = a.out.h ar.h nlist.h ranlib.h -vpath %.c $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as $(TOPSRC)/src/cmd/ld \ - $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib $(TOPSRC)/src/cmd +vpath %.c $(TOPSRC)/src/cmd/aout $(TOPSRC)/src/cmd/ar $(TOPSRC)/src/cmd/as \ + $(TOPSRC)/src/cmd/ld $(TOPSRC)/src/cmd/nm $(TOPSRC)/src/cmd/ranlib \ + $(TOPSRC)/src/cmd all install depend: $(HEADERS) $(SUBDIR) $(PROG) -for i in $(SUBDIR); do $(MAKE) -C $$i $(MFLAGS) DESTDIR=$(DESTDIR) $@; done From 1c4e56236359ab824dff7a7a7bc4fc43339a077d Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Mon, 23 Jun 2014 22:15:51 -0700 Subject: [PATCH 18/40] Added kernel configuration for PICadillo-35T board. --- src/cmd/aout/.gitignore | 1 + sys/pic32/Makefile | 2 +- sys/pic32/picadillo/Makefile | 64 +++++++++++++++++++++++++++++++++++ sys/pic32/picadillo/PICADILLO | 19 +++++++++++ sys/pic32/startup.S | 11 ++++++ sys/pic32/uart.c | 4 +-- 6 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/cmd/aout/.gitignore create mode 100644 sys/pic32/picadillo/Makefile create mode 100644 sys/pic32/picadillo/PICADILLO diff --git a/src/cmd/aout/.gitignore b/src/cmd/aout/.gitignore new file mode 100644 index 0000000..347b11f --- /dev/null +++ b/src/cmd/aout/.gitignore @@ -0,0 +1 @@ +aout diff --git a/sys/pic32/Makefile b/sys/pic32/Makefile index e82501f..dc975c9 100644 --- a/sys/pic32/Makefile +++ b/sys/pic32/Makefile @@ -5,7 +5,7 @@ SUBDIR = baremetal dip duinomite duinomite-uart duinomite-e \ duinomite-e-uart explorer16 max32 max32-eth maximite \ meb pinguino-micro starter-kit ubw32 ubw32-uart \ ubw32-uart-sdram baremetal fubarino mmb-mx7 maximite-color \ - 32mxsdram-uart + 32mxsdram-uart picadillo default: diff --git a/sys/pic32/picadillo/Makefile b/sys/pic32/picadillo/Makefile new file mode 100644 index 0000000..a2e2339 --- /dev/null +++ b/sys/pic32/picadillo/Makefile @@ -0,0 +1,64 @@ +BUILDPATH = ../../../tools/configsys/../../sys/pic32 +H = ../../../tools/configsys/../../sys/include +M = ../../../tools/configsys/../../sys/pic32 +S = ../../../tools/configsys/../../sys/kernel + +vpath %.c $(M):$(S) +vpath %.S $(M):$(S) + +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = + +DEFS += -DADC_ENABLED=YES +DEFS += -DBUS_DIV=1 +DEFS += -DBUS_KHZ=80000 +DEFS += -DCONSOLE_DEVICE=tty0 +DEFS += -DCPU_IDIV=2 +DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT +DEFS += -DGPIO_ENABLED=YES +DEFS += -DKERNEL +DEFS += -DPIC32MX7 +DEFS += -DSD0_CS_PIN=9 +DEFS += -DSD0_CS_PORT=TRISG +DEFS += -DSD0_PORT=2 +DEFS += -DUART1_BAUD=115200 +DEFS += -DUART1_ENABLED=YES +DEFS += -DUCB_METER + + +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-max32.ld + +CONFIG = PICADILLO +CONFIGPATH = ../../../tools/configsys + +include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/picadillo/PICADILLO b/sys/pic32/picadillo/PICADILLO new file mode 100644 index 0000000..bc50dc9 --- /dev/null +++ b/sys/pic32/picadillo/PICADILLO @@ -0,0 +1,19 @@ +# +# Picadillo 35T board +# =================== + +core pic32mx7 +mapping generic +linker bootloader-max32 + +device kernel cpu_khz=80000 bus_khz=80000 + +device console device=tty0 +device uart1 baud=115200 + +device rdisk +device sd0 port=2 cs=G9 + +device gpio +device adc +device foreignbootloader diff --git a/sys/pic32/startup.S b/sys/pic32/startup.S index dddbdee..44b0bd4 100644 --- a/sys/pic32/startup.S +++ b/sys/pic32/startup.S @@ -109,6 +109,17 @@ _entry_vector_: .globl _entry_vector_ jr $k0 nop +/* + * Data for bootloader. + */ + .org 0xf8 + .type _ebase, @object +_ebase: .word 0x9d000000 # EBase value + + .type _imgptr, @object +_imgptr: .word -1 # Image header pointer + + #--------------------------------------- # Exception vector: handle interrupts and exceptions # diff --git a/sys/pic32/uart.c b/sys/pic32/uart.c index d2093e7..26e2cb5 100644 --- a/sys/pic32/uart.c +++ b/sys/pic32/uart.c @@ -639,7 +639,7 @@ void uartstart (register struct tty *tp) s = spltty(); if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { out: /* Disable transmit_interrupt. */ - led_control (LED_TTY, 0); + led_control (LED_TTY, 0); splx (s); return; } @@ -705,7 +705,7 @@ again: if (--timo == 0) break; if (tp->t_state & TS_BUSY) { - uartintr (0); + uartintr (dev); goto again; } led_control (LED_TTY, 1); From 294ccae3beaf78e01f5b268b9ebd8fd094f67879 Mon Sep 17 00:00:00 2001 From: Brian Callahan Date: Thu, 10 Jul 2014 18:11:43 -0400 Subject: [PATCH 19/40] emg 1.7 --- src/cmd/emg/ChangeLog | 7 ++ src/cmd/emg/Makefile | 6 +- src/cmd/emg/basic.c | 1 - src/cmd/emg/display.c | 2 +- src/cmd/emg/ebind.h | 10 --- src/cmd/emg/efunc.h | 7 -- src/cmd/emg/emg.keys | 23 +---- src/cmd/emg/estruct.h | 33 ++++++- src/cmd/emg/search.c | 180 +++----------------------------------- src/cmd/emg/tcap.c | 27 ------ src/cmd/emg/word.c | 198 +----------------------------------------- 11 files changed, 61 insertions(+), 433 deletions(-) diff --git a/src/cmd/emg/ChangeLog b/src/cmd/emg/ChangeLog index c5d10c8..8c09437 100644 --- a/src/cmd/emg/ChangeLog +++ b/src/cmd/emg/ChangeLog @@ -1,6 +1,13 @@ ChangeLog ========= +July 10, 2014 : emg 1.7 +----------------------- +Searching now correctly updates line number display. +Remove lots of rarely-used word functions. +Remove search+replace: sed(1) is quicker. +Reduce size of some static buffers. + May 29, 2014 : emg 1.6 ---------------------- emg is now part of the RetroBSD tree. diff --git a/src/cmd/emg/Makefile b/src/cmd/emg/Makefile index ff0b3cc..87b5495 100644 --- a/src/cmd/emg/Makefile +++ b/src/cmd/emg/Makefile @@ -10,15 +10,15 @@ CFLAGS = -Os -Wall -Werror # With the extra LDFLAGS, save some bytes. CFLAGS += -ffunction-sections -fdata-sections -# This reduces code size to 46K. +# This reduces code size significantly. CFLAGS += -mips16 # Set the screen size. # Will default to FORCE_COLS=80 and FORCE_ROWS=24 # if not set here. -CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24 +#CFLAGS += -DFORCE_COLS=80 -DFORCE_ROWS=24 -# with CFLAGS+= -ffunction-sections -fdatasections +# with CFLAGS+= -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections LIBS = -ltermcap -lc diff --git a/src/cmd/emg/basic.c b/src/cmd/emg/basic.c index 75290ea..c3e86f7 100644 --- a/src/cmd/emg/basic.c +++ b/src/cmd/emg/basic.c @@ -13,7 +13,6 @@ #include "edef.h" extern int getccol(int bflg); -extern int inword(); extern void mlwrite(); extern int mlreplyt(); diff --git a/src/cmd/emg/display.c b/src/cmd/emg/display.c index ffc9979..adb36c9 100644 --- a/src/cmd/emg/display.c +++ b/src/cmd/emg/display.c @@ -647,7 +647,7 @@ void modeline(WINDOW *wp) n = 2; /* This is the version string. Do not forget to * increment when releasing a new version. */ - n += vtputs(" emg 1.6 "); + n += vtputs(" emg 1.7 "); vtputc(lchar); vtputc(lchar); diff --git a/src/cmd/emg/ebind.h b/src/cmd/emg/ebind.h index 35836dd..2356969 100644 --- a/src/cmd/emg/ebind.h +++ b/src/cmd/emg/ebind.h @@ -7,7 +7,6 @@ */ KEYTAB keytab[] = { - {CTRL | '@', setmark}, {CTRL | 'A', gotobol}, {CTRL | 'B', backchar}, {CTRL | 'D', forwdel}, @@ -50,25 +49,16 @@ KEYTAB keytab[] = { {CTLX | CTRL | 'R', fileread}, {CTLX | CTRL | 'S', filesave}, {CTLX | CTRL | 'W', filewrite}, - {META | ' ', setmark}, - {META | '%', qreplace}, {META | '.', setmark}, {META | '<', gotobob}, {META | '>', gotoeob}, {META | 'B', backword}, - {META | 'C', capword}, - {META | 'D', delfword}, {META | 'F', forwword}, {META | 'G', setline}, /* non-standard */ - {META | 'L', lowerword}, - {META | 'R', sreplace}, {META | 'S', forwsearch}, /* non-standard */ - {META | 'U', upperword}, {META | 'V', pageup}, {META | 'W', copyregion}, {META | 'Z', quickexit}, - {META | 0x7F, delbword}, - {META | CTRL | 'H', delbword}, {META | CTRL | 'N', namebuffer}, {0x7F, backdel}, {META | '[', extendedcmd}, diff --git a/src/cmd/emg/efunc.h b/src/cmd/emg/efunc.h index 00bf3ff..dd5ae85 100644 --- a/src/cmd/emg/efunc.h +++ b/src/cmd/emg/efunc.h @@ -31,8 +31,6 @@ extern int setfillcol(); /* Set fill column */ extern int setmark(); /* Set mark */ extern int forwsearch(); /* Search forward */ extern int backsearch(); /* Search backwards */ -extern int sreplace(); /* search and replace */ -extern int qreplace(); /* search and replace w/query */ extern int nextwind(); /* Move to the next window */ extern int prevwind(); /* Move to the previous window */ extern int onlywind(); /* Make current window only one */ @@ -54,11 +52,6 @@ extern int forwdel(); /* Forward delete */ extern int backdel(); /* Backward delete */ extern int killtext(); /* Kill forward */ extern int yank(); /* Yank back from killbuffer */ -extern int upperword(); /* Upper case word */ -extern int lowerword(); /* Lower case word */ -extern int capword(); /* Initial capitalize word */ -extern int delfword(); /* Delete forward word */ -extern int delbword(); /* Delete backward word */ extern int killregion(); /* Kill region */ extern int copyregion(); /* Copy region to kill buffer */ extern int quickexit(); /* low keystroke style exit */ diff --git a/src/cmd/emg/emg.keys b/src/cmd/emg/emg.keys index 9ab44fd..3f66e93 100644 --- a/src/cmd/emg/emg.keys +++ b/src/cmd/emg/emg.keys @@ -1,4 +1,4 @@ - emg keybindings (May 29, 2014) + emg keybindings (July 7, 2014) Based on Ersatz Emacs (2000/09/14) M- means to use the key prior to using another key @@ -26,12 +26,7 @@ M-G Go to line Arrow keys are active ------------------------------------------------------------------------------ FORMATTING & TRANSPOSING -M-U UPPERCASE word M-C Capitalize word -M-L lowercase word ^T Transpose characters ^Q Quote next key, so that control codes may be entered into text. (or ^X Q) -M-Q Format paragraph so that text is left-justified between margins. -^X F Set the right margin for paragraph formatting to the current position of - the cursor. ------------------------------------------------------------------------------ SEARCHING @@ -40,21 +35,10 @@ M-Q Format paragraph so that text is left-justified between margins. ENTER. Either case matches. (or M-S) ^R As above, but reverse search from cursor position. ------------------------------------------------------------------------------- - REPLACING - -M-R Replace all instances of first typed-in string with second typed-in - string. -M-% Replace with query. Answer with: - Y replace & continue N no replacement & continue - ! replace the rest ? Get a list of options - . exit and return to entry point - ^G,'q' or exit and remain at current location - ------------------------------------------------------------------------------ COPYING AND MOVING -^@ or M- Set mark at current position. +M-. Set mark at current position. ^W Delete region. M-W Copy region to kill buffer. ^Y Yank back kill buffer at cursor. @@ -64,7 +48,7 @@ position. The kill buffer is the text which has been most recently deleted or copied. Generally, the procedure for copying or moving text is: -1) Mark out region using M- at the beginning and move the cursor to +1) Mark out region using M-. at the beginning and move the cursor to the end. 2) Delete it (with ^W) or copy it (with M-W) into the kill buffer. 3) Move the cursor to the desired location and yank it back (with ^Y). @@ -113,7 +97,6 @@ M-^V Scroll other window down M-^Z Scroll other window up EXITING ^X^C Exit. Any unsaved files will require confirmation. -M-Z Write out all changed buffers automatically and exit. ------------------------------------------------------------------------------ MACROS diff --git a/src/cmd/emg/estruct.h b/src/cmd/emg/estruct.h index a5a84ef..9b2bf59 100644 --- a/src/cmd/emg/estruct.h +++ b/src/cmd/emg/estruct.h @@ -3,10 +3,10 @@ /* ESTRUCT: Structure and preprocessor */ /* internal constants */ -#define NFILEN 80 /* maximum # of bytes, file name */ +#define NFILEN 32 /* maximum # of bytes, file name */ #define NBUFN 16 /* maximum # of bytes, buffer name */ #define NLINE 512 /* maximum # of bytes, line */ -#define NKBDM 256 /* maximum # of strokes, keyboard macro */ +#define NKBDM 128 /* maximum # of strokes, keyboard macro */ #define NPAT 80 /* maximum # of bytes, pattern */ #define HUGE 32700 /* Huge number for "impossible" row&col */ @@ -31,6 +31,35 @@ #define CFCPCN 0x0001 /* Last command was C-P, C-N */ #define CFKILL 0x0002 /* Last command was a kill */ +/* + * screen constants + * override with + * CFLAGS += -DFORCE_COLS=XXX -DFORCE_ROWS=XXX + */ +#ifndef FORCE_COLS +#define FORCE_COLS 80 +#endif + +#ifndef FORCE_ROWS +#define FORCE_ROWS 24 +#endif + +/* + * XXX: + * Default/sane(?) maximum column and row sizes. + * Taken from mg1a. + * + * Let the user override these with + * CFLAGS += -DMAXCOL=XXX -DMAXROW=XXX + */ +#ifndef MAXCOL +#define MAXCOL 132 +#endif + +#ifndef MAXROW +#define MAXROW 66 +#endif + /* * There is a window structure allocated for every active display window. The * windows are kept in a big list, in top to bottom screen order, with the diff --git a/src/cmd/emg/search.c b/src/cmd/emg/search.c index 8eafae8..e9649a8 100644 --- a/src/cmd/emg/search.c +++ b/src/cmd/emg/search.c @@ -25,9 +25,6 @@ int backhunt(int f, int n); int bsearch(int f, int n); int eq(int bc, int pc); int readpattern(char *prompt); -int sreplace(int f, int n); -int qreplace(int f, int n); -int replaces(int kind, int f, int n); int forscan(char *patrn, int leavep); void expandp(char *srcstr, char *deststr, int maxlength); @@ -42,6 +39,7 @@ void expandp(char *srcstr, char *deststr, int maxlength); int forwsearch(int f, int n) { int status; + int curline = curwp->w_dotline; if (n == 0) /* resolve the repeat count */ n = 1; @@ -60,14 +58,17 @@ int forwsearch(int f, int n) } /* and complain if not there */ - if (status == FALSE) + if (status == FALSE) { mlwrite("Not found"); + curwp->w_dotline = curline; + } return (status); } int forwhunt(int f, int n) { int status = 0; + int curline = curwp->w_dotline; /* resolve the repeat count */ if (n == 0) @@ -89,8 +90,10 @@ int forwhunt(int f, int n) } /* and complain if not there */ - if (status == FALSE) + if (status == FALSE) { mlwrite("Not found"); + curwp->w_dotline = curline; + } return (status); } @@ -137,6 +140,7 @@ int bsearch(int f, int n) LINE *clp, *tlp; char *epp, *pp; int cbo, tbo, c; + int curline = curwp->w_dotline; /* find a pointer to the end of the pattern */ for (epp = &pat[0]; epp[1] != 0; ++epp) @@ -154,10 +158,12 @@ int bsearch(int f, int n) if (cbo == 0) { clp = lback(clp); + curwp->w_dotline--; if (clp == curbp->b_linep) { mlwrite("Not found"); + curwp->w_dotline = curline; return (FALSE); } cbo = llength(clp) + 1; @@ -182,6 +188,7 @@ int bsearch(int f, int n) if (tbo == 0) { tlp = lback(tlp); + curwp->w_dotline--; if (tlp == curbp->b_linep) goto fail; @@ -252,167 +259,6 @@ int readpattern(char *prompt) return (s); } -/* - * Search and replace (ESC-R) - */ -int sreplace(int f, int n) -{ - return (replaces(FALSE, f, n)); -} - -/* - * search and replace with query (ESC-CTRL-R) - */ -int qreplace(int f, int n) -{ - return (replaces(TRUE, f, n)); -} - -/* - * replaces: search for a string and replace it with another string. query - * might be enabled (according to kind) - */ -int replaces(int kind, int f, int n) -{ - LINE *origline; /* original "." position */ - char tmpc; /* temporary character */ - char c; /* input char for query */ - char tpat[NPAT]; /* temporary to hold search pattern */ - int i; /* loop index */ - int s; /* success flag on pattern inputs */ - int slength, rlength; /* length of search and replace strings */ - int numsub; /* number of substitutions */ - int nummatch; /* number of found matches */ - int nlflag; /* last char of search string a ? */ - int nlrepl; /* was a replace done on the last line? */ - int origoff; /* and offset (for . query option) */ - - /* check for negative repititions */ - if (f && n < 0) - return (FALSE); - - /* ask the user for the text of a pattern */ - if ((s = readpattern((kind == FALSE ? "Replace" : "Query replace"))) != TRUE) - return (s); - strncpy(&tpat[0], &pat[0], NPAT); /* salt it away */ - - /* ask for the replacement string */ - strncpy(&pat[0], &rpat[0], NPAT); /* set up default string */ - if ((s = readpattern("with")) == ABORT) - return (s); - - /* move everything to the right place and length them */ - strncpy(&rpat[0], &pat[0], NPAT); - strncpy(&pat[0], &tpat[0], NPAT); - slength = strlen(&pat[0]); - rlength = strlen(&rpat[0]); - - /* set up flags so we can make sure not to do a recursive replace on the - * last line */ - nlflag = (pat[slength - 1] == '\n'); - nlrepl = FALSE; - - /* build query replace question string */ - strncpy(tpat, "Replace '", 10); - expandp(&pat[0], &tpat[strlen (tpat)], NPAT / 3); - strncat(tpat, "' with '", 9); - - expandp(&rpat[0], &tpat[strlen (tpat)], NPAT / 3); - strncat(tpat, "'? ", 4); - - /* save original . position */ - origline = curwp->w_dotp; - origoff = curwp->w_doto; - - /* scan through the file */ - numsub = 0; - nummatch = 0; - while ((f == FALSE || n > nummatch) && - (nlflag == FALSE || nlrepl == FALSE)) - { - /* search for the pattern */ - if (forscan(&pat[0], PTBEG) != TRUE) - break; /* all done */ - ++nummatch; /* increment # of matches */ - - /* check if we are on the last line */ - nlrepl = (lforw (curwp->w_dotp) == curwp->w_bufp->b_linep); - - /* check for query */ - if (kind) - { - /* get the query */ - mlwrite(&tpat[0], &pat[0], &rpat[0]); - qprompt: - update(); /* show the proposed place to change */ - c = (*term.t_getchar) (); /* and input */ - mlwrite(""); /* and clear it */ - - /* and respond appropriately */ - switch (c) - { - case 'y': /* yes, substitute */ - case ' ': - break; - - case 'n': /* no, onword */ - forwchar(FALSE, 1); - continue; - - case '!': /* yes/stop asking */ - kind = FALSE; - break; - - case '.': /* abort! and return */ - /* restore old position */ - curwp->w_dotp = origline; - curwp->w_doto = origoff; - curwp->w_flag |= WFMOVE; - - case BELL: /* abort! and stay */ - mlwrite("Aborted!"); - return (FALSE); - - case 0x0d: /* controlled exit */ - case 'q': - return (TRUE); - - default: /* bitch and beep */ - (*term.t_beep) (); - - case '?': /* help me */ - mlwrite("(Y)es, (N)o, (!)Do the rest, (^G,RET,q)Abort, (.)Abort back, (?)Help: "); - goto qprompt; - } - } - /* delete the sucker */ - if (ldelete(slength, FALSE) != TRUE) - { - /* error while deleting */ - mlwrite("ERROR while deleting"); - return (FALSE); - } - /* and insert its replacement */ - for (i = 0; i < rlength; i++) - { - tmpc = rpat[i]; - s = (tmpc == '\n' ? lnewline() : linsert(1, tmpc)); - if (s != TRUE) - { - /* error while inserting */ - mlwrite("Out of memory while inserting"); - return (FALSE); - } - } - - numsub++; /* increment # of substitutions */ - } - - /* and report the results */ - mlwrite("%d substitutions", numsub); - return (TRUE); -} - /* search forward for a */ int forscan(char *patrn, int leavep) @@ -441,6 +287,7 @@ int forscan(char *patrn, int leavep) if (curoff == llength(curline)) { /* if at EOL */ curline = lforw(curline); /* skip to next line */ + curwp->w_dotline++; curoff = 0; c = '\n'; /* and return a */ } @@ -463,6 +310,7 @@ int forscan(char *patrn, int leavep) { /* advance past EOL */ matchline = lforw(matchline); + curwp->w_dotline++; matchoff = 0; c = '\n'; } diff --git a/src/cmd/emg/tcap.c b/src/cmd/emg/tcap.c index 3bf4ef6..522833d 100644 --- a/src/cmd/emg/tcap.c +++ b/src/cmd/emg/tcap.c @@ -4,33 +4,6 @@ #define termdef 1 /* don't define "term" externally */ -/* Did you remember to set FORCE_COLS? */ -#ifndef FORCE_COLS -#define FORCE_COLS 80 -#endif - -/* Did you remember to set FORCE_ROWS? */ -#ifndef FORCE_ROWS -#define FORCE_ROWS 24 -#endif - -/* - * XXX: - * Default/sane(?) maximum column and row sizes. - * Taken from mg1a. - * - * Let the user override this with a - * CFLAGS += -DMAXCOL=XXX -DMAXROW=XXX - * line in the Makefile. - */ -#ifndef MAXCOL -#define MAXCOL 132 -#endif - -#ifndef MAXROW -#define MAXROW 66 -#endif - #include /* puts(3), snprintf(3) */ #include "estruct.h" #include "edef.h" diff --git a/src/cmd/emg/word.c b/src/cmd/emg/word.c index abdc058..4943920 100644 --- a/src/cmd/emg/word.c +++ b/src/cmd/emg/word.c @@ -11,20 +11,10 @@ extern int backchar(int f, int n); extern int forwchar(int f, int n); -extern void lchange(int flag); -extern int ldelete(int n, int kflag); -extern void mlwrite(); -extern int linsert(int n, int c); -extern int lnewline(); int backword(int f, int n); int forwword(int f, int n); -int upperword(int f, int n); -int lowerword(int f, int n); -int capword(int f, int n); -int delfword(int f, int n); -int delbword(int f, int n); -int inword(); +int inword(void); /* * Move the cursor backward by "n" words. All of the details of motion are @@ -77,195 +67,11 @@ int forwword(int f, int n) return (TRUE); } -/* - * Move the cursor forward by the specified number of words. As you move, - * convert any characters to upper case. Error if you try and move beyond the - * end of the buffer. Bound to "M-U" - */ -int upperword(int f, int n) -{ - int c; - - if (n < 0) - return (FALSE); - while (n--) - { - while (inword() == FALSE) - { - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - while (inword() != FALSE) - { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (c >= 'a' && c <= 'z') - { - c -= 'a' - 'A'; - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFHARD); - } - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - } - return (TRUE); -} - -/* - * Move the cursor forward by the specified number of words. As you move - * convert characters to lower case. Error if you try and move over the end of - * the buffer. Bound to "M-L" - */ -int lowerword(int f, int n) -{ - int c; - - if (n < 0) - return (FALSE); - while (n--) - { - while (inword() == FALSE) - { - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - while (inword() != FALSE) - { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (c >= 'A' && c <= 'Z') - { - c += 'a' - 'A'; - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFHARD); - } - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - } - return (TRUE); -} - -/* - * Move the cursor forward by the specified number of words. As you move - * convert the first character of the word to upper case, and subsequent - * characters to lower case. Error if you try and move past the end of the - * buffer. Bound to "M-C" - */ -int capword(int f, int n) -{ - int c; - - if (n < 0) - return(FALSE); - while (n--) - { - while (inword() == FALSE) - { - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - if (inword() != FALSE) - { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (c >= 'a' && c <= 'z') - { - c -= 'a' - 'A'; - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFHARD); - } - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - while (inword() != FALSE) - { - c = lgetc(curwp->w_dotp, curwp->w_doto); - if (c >= 'A' && c <= 'Z') - { - c += 'a' - 'A'; - lputc(curwp->w_dotp, curwp->w_doto, c); - lchange(WFHARD); - } - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - } - } - } - return (TRUE); -} - -/* - * Kill forward by "n" words. Remember the location of dot. Move forward by - * the right number of words. Put dot back where it was and issue the kill - * command for the right number of characters. Bound to "M-D" - */ -int delfword(int f, int n) -{ - LINE *dotp; - int size, doto; - - if (n < 0) - return (FALSE); - dotp = curwp->w_dotp; - doto = curwp->w_doto; - size = 0; - while (n--) - { - while (inword() != FALSE) - { - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - ++size; - } - while (inword() == FALSE) - { - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - ++size; - } - } - curwp->w_dotp = dotp; - curwp->w_doto = doto; - return (ldelete(size, TRUE)); -} - -/* - * Kill backwards by "n" words. Move backwards by the desired number of words, - * counting the characters. When dot is finally moved to its resting place, - * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace" - */ -int delbword(int f, int n) -{ - int size; - - if (n < 0) - return (FALSE); - if (backchar(FALSE, 1) == FALSE) - return (FALSE); - size = 0; - while (n--) - { - while (inword() == FALSE) - { - if (backchar(FALSE, 1) == FALSE) - return (FALSE); - ++size; - } - while (inword() != FALSE) - { - if (backchar(FALSE, 1) == FALSE) - return (FALSE); - ++size; - } - } - if (forwchar(FALSE, 1) == FALSE) - return (FALSE); - return (ldelete(size, TRUE)); -} - /* * Return TRUE if the character at dot is a character that is considered to be * part of a word. The word character list is hard coded. Should be setable */ -int inword() +int inword(void) { int c; From 0cef044377d0003f51986547897c3d3a91237048 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Wed, 16 Jul 2014 20:31:03 -0700 Subject: [PATCH 20/40] Fsutil: added option -m to mount the filesystem via FUSE. --- tools/fsutil/Makefile | 6 +- tools/fsutil/bsdfs.h | 8 +- tools/fsutil/fsutil.c | 39 ++- tools/fsutil/inode.c | 4 +- tools/fsutil/mount.c | 748 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 787 insertions(+), 18 deletions(-) create mode 100644 tools/fsutil/mount.c diff --git a/tools/fsutil/Makefile b/tools/fsutil/Makefile index 02c4297..476e890 100644 --- a/tools/fsutil/Makefile +++ b/tools/fsutil/Makefile @@ -1,12 +1,16 @@ CC = gcc -g CFLAGS = -O -Wall DESTDIR = /usr/local -OBJS = fsutil.o superblock.o block.c inode.o create.o check.o file.o +OBJS = fsutil.o superblock.o block.c inode.o create.o check.o file.o mount.o PROG = fsutil # For Mac OS X #LIBS = -largp +# Fuse +CFLAGS += $(shell pkg-config fuse --cflags) +LIBS += $(shell pkg-config fuse --libs) + all: $(PROG) install: $(PROG) diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index d27696a..e32114b 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -52,8 +52,6 @@ */ #define MAXMNTLEN 28 -#define MAXNAMLEN 63 - #define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) #define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) @@ -135,7 +133,7 @@ typedef struct { unsigned ino; unsigned reclen; unsigned namlen; - char name [MAXNAMLEN+1]; + char name [63+1]; } fs_dirent_t; typedef void (*fs_directory_scanner_t) (fs_inode_t *dir, @@ -166,6 +164,8 @@ int fs_create (fs_t *fs, const char *filename, unsigned kbytes, int fs_check (fs_t *fs); void fs_print (fs_t *fs, FILE *out); +int fs_mount(fs_t *fs, char *dirname); + int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum); int fs_inode_save (fs_inode_t *inode, int force); void fs_inode_clear (fs_inode_t *inode); @@ -176,7 +176,7 @@ int fs_inode_read (fs_inode_t *inode, unsigned long offset, int fs_inode_write (fs_inode_t *inode, unsigned long offset, unsigned char *data, unsigned long bytes); int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); -int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, char *name, +int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, int op, int mode); int inode_build_list (fs_t *fs); diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 03a56f3..41150f0 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -37,12 +37,13 @@ int add; int newfs; int check; int fix; +int mount; unsigned kbytes; unsigned swap_kbytes; static const char *program_version = - "BSD 2.x file system utility, version 1.0\n" - "Copyright (C) 2011 Serge Vakulenko"; + "BSD 2.x file system utility, version 1.1\n" + "Copyright (C) 2011-2014 Serge Vakulenko"; static const char *program_bug_address = ""; @@ -54,6 +55,7 @@ static struct option program_options[] = { { "extract", no_argument, 0, 'x' }, { "check", no_argument, 0, 'c' }, { "fix", no_argument, 0, 'f' }, + { "mount", no_argument, 0, 'm' }, { "new", required_argument, 0, 'n' }, { "swap", required_argument, 0, 's' }, { 0 } @@ -70,11 +72,12 @@ static void print_help (char *progname) "see the GNU General Public License for more details.\n"); printf ("\n"); printf ("Usage:\n"); - printf (" %s [--verbose] filesys.bin\n", progname); - printf (" %s --add filesys.bin files...\n", progname); - printf (" %s --extract filesys.bin\n", progname); - printf (" %s --check [--fix] filesys.bin\n", progname); - printf (" %s --new=kbytes [--swap=kbytes] filesys.bin\n", progname); + printf (" %s [--verbose] filesys.img\n", progname); + printf (" %s --add filesys.img files...\n", progname); + printf (" %s --extract filesys.img\n", progname); + printf (" %s --check [--fix] filesys.img\n", progname); + printf (" %s --new=kbytes [--swap=kbytes] filesys.img\n", progname); + printf (" %s --mount filesys.img dir\n", progname); printf ("\n"); printf ("Options:\n"); printf (" -a, --add Add files to filesystem.\n"); @@ -83,7 +86,8 @@ static void print_help (char *progname) printf (" -f, --fix Fix bugs in filesystem.\n"); printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); - printf (" -v, --verbose Print verbose information.\n"); + printf (" -m, --mount Mount the filesystem.\n"); + printf (" -v, --verbose Be verbose.\n"); printf (" -V, --version Print version information and then exit.\n"); printf (" -h, --help Print this message.\n"); printf ("\n"); @@ -415,7 +419,7 @@ int main (int argc, char **argv) fs_inode_t inode; for (;;) { - key = getopt_long (argc, argv, "vaxn:cfs:", + key = getopt_long (argc, argv, "vaxmn:cfs:", program_options, 0); if (key == -1) break; @@ -439,6 +443,9 @@ int main (int argc, char **argv) case 'f': ++fix; break; + case 'm': + ++mount; + break; case 's': swap_kbytes = strtol (optarg, 0, 0); break; @@ -454,8 +461,9 @@ int main (int argc, char **argv) } } i = optind; - if ((! add && i != argc-1) || (add && i >= argc) || - (extract + newfs + check + add > 1) || + if ((! add && ! mount && i != argc-1) || (add && i >= argc) || + (mount && i != argc-2) || + (extract + newfs + check + add + mount > 1) || (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { print_help (argv[0]); return -1; @@ -509,6 +517,15 @@ int main (int argc, char **argv) return 0; } + if (mount) { + /* Mount the filesystem. */ + if (++i >= argc) { + print_help (argv[0]); + return -1; + } + return fs_mount(&fs, argv[i]); + } + /* Print the structure of flesystem. */ fs_print (&fs, stdout); if (verbose) { diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index 881df87..d2e8696 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -544,12 +544,12 @@ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) #define DELETE 2 /* setup for file deletion */ #define LINK 3 /* setup for link */ -int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, char *name, +int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, int op, int mode) { fs_inode_t dir; int c, namlen, reclen; - char *namptr; + const char *namptr; unsigned long offset, last_offset; struct { unsigned int inum; diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c new file mode 100644 index 0000000..2534c65 --- /dev/null +++ b/tools/fsutil/mount.c @@ -0,0 +1,748 @@ +/* + * Mount 2.xBSD filesystem via FUSE interface. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include +#include +#include +#include +#include + +#define FUSE_USE_VERSION 26 +#include + +#include "bsdfs.h" + +extern int verbose; + +/* + * Print a message to log file. + */ +static void printlog(const char *format, ...) +{ + va_list ap; + + if (verbose) { + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fflush(stderr); + } +} + +/* + * Get file attributes. + * + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are + * ignored. The 'st_ino' field is ignored except if the 'use_ino' + * mount option is given. + */ +int op_getattr(const char *path, struct stat *statbuf) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir; + + printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", + path, statbuf); + + if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { + printlog("--- cannot find path %s\n", path); + return -ENOENT; + } + + switch (dir.mode & INODE_MODE_FMT) { /* type of file */ + case INODE_MODE_FREG: /* regular */ + statbuf->st_mode = S_IFREG; + break; + case INODE_MODE_FDIR: /* directory */ + statbuf->st_mode = S_IFDIR; + break; + case INODE_MODE_FCHR: /* character special */ + statbuf->st_mode = S_IFCHR; + break; + case INODE_MODE_FBLK: /* block special */ + statbuf->st_mode = S_IFBLK; + break; + case INODE_MODE_FLNK: /* symbolic link */ + statbuf->st_mode = S_IFLNK; + break; + case INODE_MODE_FSOCK: /* socket */ + statbuf->st_mode = S_IFSOCK; + break; + default: /* cannot happen */ + printlog("--- unknown file type %#x\n", dir.mode & INODE_MODE_FMT); + return -ENOENT; + } + statbuf->st_mode |= dir.mode & 07777; /* protection */ + statbuf->st_ino = dir.number; /* inode number */ + statbuf->st_nlink = dir.nlink; /* number of hard links */ + statbuf->st_uid = dir.uid; /* user ID of owner */ + statbuf->st_gid = dir.gid; /* group ID of owner */ + statbuf->st_rdev = dir.addr[1]; /* device ID (if special file) */ + statbuf->st_size = dir.size; /* total size, in bytes */ + statbuf->st_blocks = dir.size >> 9; /* number of 512B blocks allocated */ + statbuf->st_atime = dir.atime; /* time of last access */ + statbuf->st_mtime = dir.mtime; /* time of last modification */ + statbuf->st_ctime = dir.ctime; /* time of last status change */ + return 0; +} + +/* + * Get attributes from an open file + * + * This method is called instead of the getattr() method if the + * file information is available. + * + * Currently this is only called after the create() method if that + * is implemented (see above). Later it may be called for + * invocations of fstat() too. + */ +int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) +{ + printlog("--- op_fgetattr(path=\"%s\", statbuf=%p, fi=%p)\n", + path, statbuf, fi); + + // On FreeBSD, trying to do anything with the mountpoint ends up + // opening it, and then using the FD for an fgetattr. So in the + // special case of a path of "/", I need to do a getattr on the + // underlying root directory instead of doing the fgetattr(). + if (strcmp(path, "/") == 0) + return op_getattr(path, statbuf); + + //TODO + //retstat = fstat(fi->fh, statbuf); + //if (retstat < 0) + // retstat = print_errno("op_fgetattr fstat"); + + return 0; +} + +/* + * Read the target of a symbolic link + * + * The buffer should be filled with a null terminated string. The + * buffer size argument includes the space for the terminating + * null character. If the linkname is too long to fit in the + * buffer, it should be truncated. The return value should be 0 + * for success. + */ +// Note the system readlink() will truncate and lose the terminating +// null. So, the size passed to to the system readlink() must be one +// less than the size passed to op_readlink() +// op_readlink() code by Bernardo F Costa (thanks!) +int op_readlink(const char *path, char *link, size_t size) +{ + printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", + path, link, size); + + //retstat = readlink(path, link, size - 1); + //if (retstat < 0) + // retstat = print_errno("op_readlink readlink"); + //else { + // link[retstat] = '\0'; + // retstat = 0; + //} + + return 0; +} + +/* + * Create a file node + * + * There is no create() operation, mknod() will be called for + * creation of all non-directory, non-symlink nodes. + */ +int op_mknod(const char *path, mode_t mode, dev_t dev) +{ + printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", + path, mode, dev); + + //TODO + //if (S_ISREG(mode)) { + // retstat = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); + // if (retstat < 0) + // retstat = print_errno("op_mknod open"); + // else { + // retstat = close(retstat); + // if (retstat < 0) + // retstat = print_errno("op_mknod close"); + // } + //} else if (S_ISFIFO(mode)) { + // retstat = mkfifo(path, mode); + // if (retstat < 0) + // retstat = print_errno("op_mknod mkfifo"); + //} else { + // retstat = mknod(path, mode, dev); + // if (retstat < 0) + // retstat = print_errno("op_mknod mknod"); + //} + return 0; +} + +/* + * Create a directory + */ +int op_mkdir(const char *path, mode_t mode) +{ + printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", + path, mode); + + //TODO + //retstat = mkdir(path, mode); + //if (retstat < 0) + // retstat = print_errno("op_mkdir mkdir"); + + return 0; +} + +/* + * Remove a file + */ +int op_unlink(const char *path) +{ + printlog("op_unlink(path=\"%s\")\n", + path); + + //TODO + //retstat = unlink(path); + //if (retstat < 0) + // retstat = print_errno("op_unlink unlink"); + + return 0; +} + +/* + * Remove a directory + */ +int op_rmdir(const char *path) +{ + printlog("op_rmdir(path=\"%s\")\n", + path); + + //TODO + //retstat = rmdir(path); + //if (retstat < 0) + // retstat = print_errno("op_rmdir rmdir"); + + return 0; +} + +/* + * Create a symbolic link + * The parameters here are a little bit confusing, but do correspond + * to the symlink() system call. The 'path' is where the link points, + * while the 'link' is the link itself. So we need to leave the path + * unaltered, but insert the link into the mounted directory. + */ +int op_symlink(const char *path, const char *link) +{ + printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", + path, link); + + //TODO + //retstat = symlink(path, link); + //if (retstat < 0) + // retstat = print_errno("op_symlink symlink"); + + return 0; +} + +/* + * Rename a file + * + * Both path and newpath are fs-relative. + */ +int op_rename(const char *path, const char *newpath) +{ + printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", + path, newpath); + + //TODO + //retstat = rename(path, newpath); + //if (retstat < 0) + // retstat = print_errno("op_rename rename"); + + return 0; +} + +/* + * Create a hard link to a file + */ +int op_link(const char *path, const char *newpath) +{ + printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", + path, newpath); + + //TODO + //retstat = link(path, newpath); + //if (retstat < 0) + // retstat = print_errno("op_link link"); + + return 0; +} + +/* + * Change the permission bits of a file + */ +int op_chmod(const char *path, mode_t mode) +{ + printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", + path, mode); + + //TODO + //retstat = chmod(path, mode); + //if (retstat < 0) + // retstat = print_errno("op_chmod chmod"); + + return 0; +} + +/* + * Change the owner and group of a file + */ +int op_chown(const char *path, uid_t uid, gid_t gid) + +{ + printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", + path, uid, gid); + + //TODO + //retstat = chown(path, uid, gid); + //if (retstat < 0) + // retstat = print_errno("op_chown chown"); + + return 0; +} + +/* + * Change the size of a file + */ +int op_truncate(const char *path, off_t newsize) +{ + printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", + path, newsize); + + //TODO + //retstat = truncate(path, newsize); + //if (retstat < 0) + // print_errno("op_truncate truncate"); + + return 0; +} + +/* + * Change the access and/or modification times of a file + */ +int op_utime(const char *path, struct utimbuf *ubuf) +{ + printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", + path, ubuf); + + //TODO + //retstat = utime(path, ubuf); + //if (retstat < 0) + // retstat = print_errno("op_utime utime"); + + return 0; +} + +/* + * File open operation + * + * No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC) + * will be passed to open(). Open should check if the operation + * is permitted for the given flags. Optionally open may also + * return an arbitrary filehandle in the fuse_file_info structure, + * which will be passed to all file operations. + */ +int op_open(const char *path, struct fuse_file_info *fi) +{ + int fd = 0; + + printlog("--- op_open(path\"%s\", fi=%p)\n", + path, fi); + + //TODO + //fd = open(path, fi->flags); + //if (fd < 0) + // retstat = print_errno("op_open open"); + + fi->fh = fd; + + return 0; +} + +/* + * Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + */ +int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) +{ + printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + //TODO + //retstat = pread(fi->fh, buf, size, offset); + //if (retstat < 0) + // retstat = print_errno("op_read read"); + + return 0; +} + +/* + * Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + */ +int op_write(const char *path, const char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + //TODO + //retstat = pwrite(fi->fh, buf, size, offset); + //if (retstat < 0) + // retstat = print_errno("op_write pwrite"); + + return 0; +} + +/* + * Get file system statistics + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + */ +int op_statfs(const char *path, struct statvfs *statv) +{ + printlog("--- op_statfs(path=\"%s\", statv=%p)\n", + path, statv); + + // get stats for underlying filesystem + //TODO + //retstat = statvfs(path, statv); + //if (retstat < 0) + // retstat = print_errno("op_statfs statvfs"); + + return 0; +} + +/* + * Possibly flush cached data + * + * BIG NOTE: This is not equivalent to fsync(). It's not a + * request to sync dirty data. + * + * Flush is called on each close() of a file descriptor. So if a + * filesystem wants to return write errors in close() and the file + * has cached dirty data, this is a good place to write back data + * and return any errors. Since many applications ignore close() + * errors this is not always useful. + * + * NOTE: The flush() method may be called more than once for each + * open(). This happens if more than one file descriptor refers + * to an opened file due to dup(), dup2() or fork() calls. It is + * not possible to determine if a flush is final, so each flush + * should be treated equally. Multiple write-flush sequences are + * relatively rare, so this shouldn't be a problem. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + */ +int op_flush(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_flush(path=\"%s\", fi=%p)\n", path, fi); + return 0; +} + +/* + * Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + */ +int op_release(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_release(path=\"%s\", fi=%p)\n", + path, fi); + + //TODO + // We need to close the file. Had we allocated any resources + // (buffers etc) we'd need to free them here as well. + //retstat = close(fi->fh); + + return 0; +} + +/* + * Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + */ +int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) +{ + printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", + path, datasync, fi); + + //TODO + //retstat = fsync(fi->fh); + //if (retstat < 0) + // print_errno("op_fsync fsync"); + + return 0; +} + +/* + * Open directory + * + * This method should check if the open operation is permitted for + * this directory + */ +int op_opendir(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_opendir(path=\"%s\", fi=%p)\n", + path, fi); + return 0; +} + +/* + * Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. + * + * The filesystem may choose between two modes of operation: + * + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. + * + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + */ +int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, + struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir; + char name [BSDFS_BSIZE - 12]; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; + + printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", + path, buf, filler, offset, fi); + + if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { + printlog("--- cannot find path %s\n", path); + return -ENOENT; + } + + /* Copy the entire directory into the buffer. */ + for (offset = 0; offset < dir.size; offset += dirent.reclen) { + if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + printlog("--- read error at offset %ld\n", offset); + return -EIO; + } + //printlog("--- readdir offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); + + if (! fs_inode_read (&dir, offset+sizeof(dirent), + (unsigned char*)name, (dirent.namlen + 4) / 4 * 4)) + { + printlog("--- name read error at offset %ld\n", offset); + return -EIO; + } + //printlog("--- readdir offset %lu: name='%s'\n", offset, name); + + if (dirent.inum != 0) { + //printlog("calling filler with name %s\n", name); + if (filler(buf, name, NULL, 0) != 0) { + printlog(" ERROR op_readdir filler: buffer full"); + return -ENOMEM; + } + } + } + return 0; +} + +/* + * Release directory + */ +int op_releasedir(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", + path, fi); + return 0; +} + +/* + * Clean up filesystem + * + * Called on filesystem exit. + */ +void op_destroy(void *userdata) +{ + printlog("--- op_destroy(userdata=%p)\n", userdata); +} + +/* + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + */ +int op_access(const char *path, int mask) +{ + printlog("--- op_access(path=\"%s\", mask=0%o)\n", + path, mask); + + /* Always permitted. */ + return 0; +} + +/* + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + */ +int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + int fd = 0; + + printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", + path, mode, fi); + + //TODO + //fd = creat(path, mode); + //if (fd < 0) + // retstat = print_errno("op_create creat"); + + fi->fh = fd; + + return 0; +} + +/* + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + */ +int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) +{ + printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", + path, offset, fi); + + //TODO + //retstat = ftruncate(fi->fh, offset); + //if (retstat < 0) + // retstat = print_errno("op_ftruncate ftruncate"); + + return 0; +} + +static struct fuse_operations mount_ops = { + .access = op_access, + .chmod = op_chmod, + .chown = op_chown, + .create = op_create, // + .destroy = op_destroy, // + .fgetattr = op_fgetattr, // + .flush = op_flush, // + .fsync = op_fsync, + .ftruncate = op_ftruncate, // + .getattr = op_getattr, + .link = op_link, + .mkdir = op_mkdir, + .mknod = op_mknod, + .open = op_open, + .opendir = op_opendir, // + .readdir = op_readdir, + .readlink = op_readlink, + .read = op_read, + .release = op_release, + .releasedir = op_releasedir, // + .rename = op_rename, + .rmdir = op_rmdir, + .statfs = op_statfs, + .symlink = op_symlink, + .truncate = op_truncate, + .unlink = op_unlink, + .utime = op_utime, // + .write = op_write, +}; + +int fs_mount(fs_t *fs, char *dirname) +{ + char *av[8]; + int ret, ac; + + printf ("Filesystem mounted as %s\n", dirname); + printf ("Press ^C to unmount\n"); + + /* Invoke FUSE to mount the filesystem. */ + ac = 0; + av[ac++] = "fsutil"; + av[ac++] = "-f"; // foreground + av[ac++] = "-s"; // single-threaded + if (verbose > 1) + av[ac++] = "-d"; // debug + av[ac++] = dirname; + av[ac] = 0; + ret = fuse_main(ac, av, &mount_ops, fs); + if (ret != 0) { + perror ("fuse_main failed"); + return -1; + } + printf ("\nFilesystem %s unmounted\n", dirname); + return ret; +} From 08c79d7fec7ddbb462a1678329d7f6c3d9166fdb Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 17 Jul 2014 20:16:25 -0700 Subject: [PATCH 21/40] Fsutil --mount can read and write files. --- tools/fsutil/bsdfs.h | 4 +- tools/fsutil/file.c | 10 +- tools/fsutil/fsutil.c | 2 +- tools/fsutil/inode.c | 14 +- tools/fsutil/mount.c | 422 ++++++++++++++++++++++-------------------- 5 files changed, 238 insertions(+), 214 deletions(-) diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index e32114b..831a67d 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -193,8 +193,8 @@ void fs_directory_scan (fs_inode_t *inode, char *dirname, void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent); void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data); -int fs_file_create (fs_t *fs, fs_file_t *file, char *name, int mode); -int fs_file_open (fs_t *fs, fs_file_t *file, char *name, int wflag); +int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode); +int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag); int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes); int fs_file_write (fs_file_t *file, unsigned char *data, diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 06d5312..4fea8fa 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -27,7 +27,7 @@ extern int verbose; -int fs_file_create (fs_t *fs, fs_file_t *file, char *name, int mode) +int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { if (! fs_inode_by_name (fs, &file->inode, name, 1, mode)) { fprintf (stderr, "%s: inode open failed\n", name); @@ -44,7 +44,7 @@ int fs_file_create (fs_t *fs, fs_file_t *file, char *name, int mode) return 1; } -int fs_file_open (fs_t *fs, fs_file_t *file, char *name, int wflag) +int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { if (! fs_inode_by_name (fs, &file->inode, name, 0, 0)) { fprintf (stderr, "%s: inode open failed\n", name); @@ -62,8 +62,8 @@ int fs_file_open (fs_t *fs, fs_file_t *file, char *name, int wflag) int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes) { if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file write failed\n", - file->inode.number); + fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); return 0; } file->offset += bytes; @@ -75,7 +75,7 @@ int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes) if (! file->writable) return 0; if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: error writing %lu bytes at offset %lu\n", + fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", file->inode.number, bytes, file->offset); return 0; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 41150f0..c1b6887 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -492,7 +492,7 @@ int main (int argc, char **argv) } /* Add or extract or info. */ - if (! fs_open (&fs, argv[i], (add != 0))) { + if (! fs_open (&fs, argv[i], (add + mount != 0))) { fprintf (stderr, "%s: cannot open\n", argv[i]); return -1; } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index d2e8696..a2c567c 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -440,6 +440,7 @@ int fs_inode_read (fs_inode_t *inode, unsigned long offset, if (! fs_read_block (inode->fs, bn, block)) return 0; memcpy (data, block + inblock_offset, n); + data += n; offset += n; bytes -= n; } @@ -482,6 +483,7 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, if (! fs_write_block (inode->fs, bn, block)) return 0; } + data += n; offset += n; bytes -= n; } @@ -642,7 +644,7 @@ cloop: */ create_file: if (! fs_inode_alloc (fs, inode)) { - fprintf (stderr, "%s: cannot allocate inode\n", name); + fprintf (stderr, "%s: cannot allocate inode\n", namptr); return 0; } inode->dirty = 1; @@ -675,7 +677,7 @@ create_file: ++inode->nlink; } if (! fs_inode_save (inode, 0)) { - fprintf (stderr, "%s: cannot save file inode\n", name); + fprintf (stderr, "%s: cannot save file inode\n", namptr); return 0; } @@ -723,7 +725,7 @@ create_file: /* Align directory size. */ dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); + fprintf (stderr, "%s: cannot save directory inode\n", namptr); return 0; } return 2; @@ -735,7 +737,7 @@ delete_file: if (verbose > 2) printf ("*** delete inode %d\n", dirent.inum); if (! fs_inode_get (fs, inode, dirent.inum)) { - fprintf (stderr, "%s: cannot get inode %d\n", name, dirent.inum); + fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); return 0; } inode->dirty = 1; @@ -762,7 +764,7 @@ delete_file: return 0; } if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); + fprintf (stderr, "%s: cannot save directory inode\n", namptr); return 0; } return 2; @@ -801,7 +803,7 @@ create_link: return 0; } if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", name); + fprintf (stderr, "%s: cannot save directory inode\n", namptr); return 0; } *inode = dir; diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 2534c65..1d05a9b 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -35,6 +35,12 @@ extern int verbose; +/* + * File descriptor to be used by op_open(), op_create(), op_read(), + * op_write(), op_release(), op_fgetattr(), op_fsync(), op_ftruncate(). + */ +static fs_file_t file; + /* * Print a message to log file. */ @@ -50,6 +56,51 @@ static void printlog(const char *format, ...) } } +/* + * Copy data to struct stat. + */ +static int getstat (fs_inode_t *inode, struct stat *statbuf) +{ + statbuf->st_mode = inode->mode & 07777; /* protection */ + statbuf->st_ino = inode->number; /* inode number */ + statbuf->st_nlink = inode->nlink; /* number of hard links */ + statbuf->st_uid = inode->uid; /* user ID of owner */ + statbuf->st_gid = inode->gid; /* group ID of owner */ + statbuf->st_rdev = 0; /* device ID (if special file) */ + statbuf->st_size = inode->size; /* total size, in bytes */ + statbuf->st_blocks = inode->size >> 9; /* number of blocks allocated */ + statbuf->st_atime = inode->atime; /* time of last access */ + statbuf->st_mtime = inode->mtime; /* time of last modification */ + statbuf->st_ctime = inode->ctime; /* time of last status change */ + + switch (inode->mode & INODE_MODE_FMT) { /* type of file */ + case INODE_MODE_FREG: /* regular */ + statbuf->st_mode |= S_IFREG; + break; + case INODE_MODE_FDIR: /* directory */ + statbuf->st_mode |= S_IFDIR; + break; + case INODE_MODE_FCHR: /* character special */ + statbuf->st_mode |= S_IFCHR; + statbuf->st_rdev = inode->addr[1]; + break; + case INODE_MODE_FBLK: /* block special */ + statbuf->st_mode |= S_IFBLK; + statbuf->st_rdev = inode->addr[1]; + break; + case INODE_MODE_FLNK: /* symbolic link */ + statbuf->st_mode |= S_IFLNK; + break; + case INODE_MODE_FSOCK: /* socket */ + statbuf->st_mode |= S_IFSOCK; + break; + default: /* cannot happen */ + printlog("--- unknown file type %#x\n", inode->mode & INODE_MODE_FMT); + return -ENOENT; + } + return 0; +} + /* * Get file attributes. * @@ -60,51 +111,16 @@ static void printlog(const char *format, ...) int op_getattr(const char *path, struct stat *statbuf) { fs_t *fs = fuse_get_context()->private_data; - fs_inode_t dir; + fs_inode_t inode; printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); - if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { - printlog("--- cannot find path %s\n", path); + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- search failed\n"); return -ENOENT; } - - switch (dir.mode & INODE_MODE_FMT) { /* type of file */ - case INODE_MODE_FREG: /* regular */ - statbuf->st_mode = S_IFREG; - break; - case INODE_MODE_FDIR: /* directory */ - statbuf->st_mode = S_IFDIR; - break; - case INODE_MODE_FCHR: /* character special */ - statbuf->st_mode = S_IFCHR; - break; - case INODE_MODE_FBLK: /* block special */ - statbuf->st_mode = S_IFBLK; - break; - case INODE_MODE_FLNK: /* symbolic link */ - statbuf->st_mode = S_IFLNK; - break; - case INODE_MODE_FSOCK: /* socket */ - statbuf->st_mode = S_IFSOCK; - break; - default: /* cannot happen */ - printlog("--- unknown file type %#x\n", dir.mode & INODE_MODE_FMT); - return -ENOENT; - } - statbuf->st_mode |= dir.mode & 07777; /* protection */ - statbuf->st_ino = dir.number; /* inode number */ - statbuf->st_nlink = dir.nlink; /* number of hard links */ - statbuf->st_uid = dir.uid; /* user ID of owner */ - statbuf->st_gid = dir.gid; /* group ID of owner */ - statbuf->st_rdev = dir.addr[1]; /* device ID (if special file) */ - statbuf->st_size = dir.size; /* total size, in bytes */ - statbuf->st_blocks = dir.size >> 9; /* number of 512B blocks allocated */ - statbuf->st_atime = dir.atime; /* time of last access */ - statbuf->st_mtime = dir.mtime; /* time of last modification */ - statbuf->st_ctime = dir.ctime; /* time of last status change */ - return 0; + return getstat (&inode, statbuf); } /* @@ -129,11 +145,141 @@ int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *f if (strcmp(path, "/") == 0) return op_getattr(path, statbuf); - //TODO - //retstat = fstat(fi->fh, statbuf); - //if (retstat < 0) - // retstat = print_errno("op_fgetattr fstat"); + if (file.inode.mode == 0) + return -EBADF; + return getstat (&file.inode, statbuf); +} + +/* + * File open operation + * + * No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC) + * will be passed to open(). Open should check if the operation + * is permitted for the given flags. Optionally open may also + * return an arbitrary filehandle in the fuse_file_info structure, + * which will be passed to all file operations. + */ +int op_open(const char *path, struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + int write_flag = (fi->flags & O_ACCMODE) != O_RDONLY; + + printlog("--- op_open(path=\"%s\", fi=%p) flags=%#x \n", + path, fi, fi->flags); + + if (! fs_file_open (fs, &file, path, write_flag)) { + printlog("--- open failed\n"); + return -ENOENT; + } + + if (fi->flags & O_APPEND) { + file.offset = file.inode.size; + } + return 0; +} + +/* + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + */ +int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) +{ + fs_t *fs = fuse_get_context()->private_data; + + printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", + path, mode, fi); + + file.inode.mode = 0; + if (! fs_file_create (fs, &file, path, mode & 07777)) { + printlog("--- create failed\n"); + if ((file.inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) + return -EISDIR; + return -EIO; + } + return 0; +} + +/* + * Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + */ +int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) +{ + printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + if (offset >= file.inode.size) + return 0; + + file.offset = offset; + if (size > file.inode.size - offset) + size = file.inode.size - offset; + + if (! fs_file_read (&file, (unsigned char*) buf, size)) { + printlog("--- read failed\n"); + return -EIO; + } + printlog("--- read returned %u\n", size); + return size; +} + +/* + * Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + */ +int op_write(const char *path, const char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) +{ + printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", + path, buf, size, offset, fi); + + file.offset = offset; + if (! fs_file_write (&file, (unsigned char*) buf, size)) { + printlog("--- read failed\n"); + return -EIO; + } + return size; +} + +/* + * Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + */ +int op_release(const char *path, struct fuse_file_info *fi) +{ + printlog("--- op_release(path=\"%s\", fi=%p)\n", + path, fi); + + if (file.inode.mode == 0) + return -EBADF; + + fs_file_close (&file); + file.inode.mode = 0; return 0; } @@ -155,6 +301,7 @@ int op_readlink(const char *path, char *link, size_t size) printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", path, link, size); + //TODO //retstat = readlink(path, link, size - 1); //if (retstat < 0) // retstat = print_errno("op_readlink readlink"); @@ -321,7 +468,6 @@ int op_chmod(const char *path, mode_t mode) * Change the owner and group of a file */ int op_chown(const char *path, uid_t uid, gid_t gid) - { printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); @@ -366,76 +512,6 @@ int op_utime(const char *path, struct utimbuf *ubuf) return 0; } -/* - * File open operation - * - * No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC) - * will be passed to open(). Open should check if the operation - * is permitted for the given flags. Optionally open may also - * return an arbitrary filehandle in the fuse_file_info structure, - * which will be passed to all file operations. - */ -int op_open(const char *path, struct fuse_file_info *fi) -{ - int fd = 0; - - printlog("--- op_open(path\"%s\", fi=%p)\n", - path, fi); - - //TODO - //fd = open(path, fi->flags); - //if (fd < 0) - // retstat = print_errno("op_open open"); - - fi->fh = fd; - - return 0; -} - -/* - * Read data from an open file - * - * Read should return exactly the number of bytes requested except - * on EOF or error, otherwise the rest of the data will be - * substituted with zeroes. An exception to this is when the - * 'direct_io' mount option is specified, in which case the return - * value of the read system call will reflect the return value of - * this operation. - */ -int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) -{ - printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); - - //TODO - //retstat = pread(fi->fh, buf, size, offset); - //if (retstat < 0) - // retstat = print_errno("op_read read"); - - return 0; -} - -/* - * Write data to an open file - * - * Write should return exactly the number of bytes requested - * except on error. An exception to this is when the 'direct_io' - * mount option is specified (see read operation). - */ -int op_write(const char *path, const char *buf, size_t size, off_t offset, - struct fuse_file_info *fi) -{ - printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); - - //TODO - //retstat = pwrite(fi->fh, buf, size, offset); - //if (retstat < 0) - // retstat = print_errno("op_write pwrite"); - - return 0; -} - /* * Get file system statistics * @@ -483,32 +559,6 @@ int op_flush(const char *path, struct fuse_file_info *fi) return 0; } -/* - * Release an open file - * - * Release is called when there are no more references to an open - * file: all file descriptors are closed and all memory mappings - * are unmapped. - * - * For every open() call there will be exactly one release() call - * with the same flags and file descriptor. It is possible to - * have a file opened more than once, in which case only the last - * release will mean, that no more reads/writes will happen on the - * file. The return value of release is ignored. - */ -int op_release(const char *path, struct fuse_file_info *fi) -{ - printlog("--- op_release(path=\"%s\", fi=%p)\n", - path, fi); - - //TODO - // We need to close the file. Had we allocated any resources - // (buffers etc) we'd need to free them here as well. - //retstat = close(fi->fh); - - return 0; -} - /* * Synchronize file contents * @@ -520,11 +570,10 @@ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", path, datasync, fi); - //TODO - //retstat = fsync(fi->fh); - //if (retstat < 0) - // print_errno("op_fsync fsync"); - + if (datasync == 0 && file.writable) { + if (! fs_inode_save (&file.inode, 0)) + return -EIO; + } return 0; } @@ -644,33 +693,6 @@ int op_access(const char *path, int mask) return 0; } -/* - * Create and open a file - * - * If the file does not exist, first create it with the specified - * mode, and then open it. - * - * If this method is not implemented or under Linux kernel - * versions earlier than 2.6.15, the mknod() and open() methods - * will be called instead. - */ -int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) -{ - int fd = 0; - - printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", - path, mode, fi); - - //TODO - //fd = creat(path, mode); - //if (fd < 0) - // retstat = print_errno("op_create creat"); - - fi->fh = fd; - - return 0; -} - /* * Change the size of an open file * @@ -691,34 +713,34 @@ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) } static struct fuse_operations mount_ops = { - .access = op_access, - .chmod = op_chmod, - .chown = op_chown, - .create = op_create, // - .destroy = op_destroy, // - .fgetattr = op_fgetattr, // - .flush = op_flush, // - .fsync = op_fsync, - .ftruncate = op_ftruncate, // - .getattr = op_getattr, - .link = op_link, - .mkdir = op_mkdir, - .mknod = op_mknod, - .open = op_open, - .opendir = op_opendir, // - .readdir = op_readdir, - .readlink = op_readlink, - .read = op_read, - .release = op_release, - .releasedir = op_releasedir, // - .rename = op_rename, - .rmdir = op_rmdir, - .statfs = op_statfs, - .symlink = op_symlink, - .truncate = op_truncate, - .unlink = op_unlink, - .utime = op_utime, // - .write = op_write, + .access = op_access, + .chmod = op_chmod, + .chown = op_chown, + .create = op_create, + .destroy = op_destroy, + .fgetattr = op_fgetattr, + .flush = op_flush, + .fsync = op_fsync, + .ftruncate = op_ftruncate, + .getattr = op_getattr, + .link = op_link, + .mkdir = op_mkdir, + .mknod = op_mknod, + .open = op_open, + .opendir = op_opendir, + .readdir = op_readdir, + .readlink = op_readlink, + .read = op_read, + .release = op_release, + .releasedir = op_releasedir, + .rename = op_rename, + .rmdir = op_rmdir, + .statfs = op_statfs, + .symlink = op_symlink, + .truncate = op_truncate, + .unlink = op_unlink, + .utime = op_utime, + .write = op_write, }; int fs_mount(fs_t *fs, char *dirname) From 847e2bff771dc881839f3d82aa43cb324b286e89 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 17 Jul 2014 21:31:49 -0700 Subject: [PATCH 22/40] Fsutil: allow truncate to arbitrary length. --- tools/fsutil/block.c | 39 ++++++++++++++++++++++++++++----------- tools/fsutil/bsdfs.h | 8 ++++---- tools/fsutil/file.c | 2 +- tools/fsutil/inode.c | 39 +++++++++++++++++++++++++-------------- tools/fsutil/mount.c | 6 ++++++ 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/tools/fsutil/block.c b/tools/fsutil/block.c index 5aa53ba..c1a880f 100644 --- a/tools/fsutil/block.c +++ b/tools/fsutil/block.c @@ -84,7 +84,7 @@ int fs_block_free (fs_t *fs, unsigned int bno) /* * Free an indirect block. */ -int fs_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { unsigned nb; unsigned char data [BSDFS_BSIZE]; @@ -94,8 +94,13 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno) fprintf (stderr, "inode_clear: read error at block %d\n", bno); return 0; } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; if (nb) fs_block_free (fs, nb); } @@ -106,7 +111,7 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno) /* * Free a double indirect block. */ -int fs_double_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { unsigned nb; unsigned char data [BSDFS_BSIZE]; @@ -116,10 +121,16 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno) fprintf (stderr, "inode_clear: read error at block %d\n", bno); return 0; } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; if (nb) - fs_indirect_block_free (fs, nb); + fs_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4); } fs_block_free (fs, bno); return 1; @@ -128,7 +139,7 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno) /* * Free a triple indirect block. */ -int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno) +int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { unsigned nb; unsigned char data [BSDFS_BSIZE]; @@ -138,10 +149,16 @@ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno) fprintf (stderr, "inode_clear: read error at block %d\n", bno); return 0; } - for (i=BSDFS_BSIZE-2; i>=0; i-=2) { - nb = data [i+1] << 8 | data [i]; + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; if (nb) - fs_double_indirect_block_free (fs, nb); + fs_double_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); } fs_block_free (fs, bno); return 1; diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index 831a67d..7b5954d 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -169,7 +169,7 @@ int fs_mount(fs_t *fs, char *dirname); int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum); int fs_inode_save (fs_inode_t *inode, int force); void fs_inode_clear (fs_inode_t *inode); -void fs_inode_truncate (fs_inode_t *inode); +void fs_inode_truncate (fs_inode_t *inode, unsigned long size); void fs_inode_print (fs_inode_t *inode, FILE *out); int fs_inode_read (fs_inode_t *inode, unsigned long offset, unsigned char *data, unsigned long bytes); @@ -184,9 +184,9 @@ int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data); int fs_block_free (fs_t *fs, unsigned int bno); int fs_block_alloc (fs_t *fs, unsigned int *bno); -int fs_indirect_block_free (fs_t *fs, unsigned int bno); -int fs_double_indirect_block_free (fs_t *fs, unsigned int bno); -int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno); +int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); +int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); +int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); void fs_directory_scan (fs_inode_t *inode, char *dirname, fs_directory_scanner_t scanner, void *arg); diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 4fea8fa..3d0275e 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -37,7 +37,7 @@ int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) /* Cannot open directory on write. */ return 0; } - fs_inode_truncate (&file->inode); + fs_inode_truncate (&file->inode, 0); fs_inode_save (&file->inode, 0); file->writable = 1; file->offset = 0; diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index a2c567c..418f953 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -90,35 +90,46 @@ int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) * a contiguous free list much longer * than FIFO. */ -void fs_inode_truncate (fs_inode_t *inode) +void fs_inode_truncate (fs_inode_t *inode, unsigned long size) { + int i, nblk; unsigned *blk; if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) return; -#define SINGLE 4 /* index of single indirect block */ -#define DOUBLE 5 /* index of double indirect block */ -#define TRIPLE 6 /* index of triple indirect block */ +#define SINGLE NDADDR /* index of single indirect block */ +#define DOUBLE (SINGLE+1) /* index of double indirect block */ +#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ - for (blk = &inode->addr[TRIPLE]; blk >= &inode->addr[0]; --blk) { + nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; + for (i=TRIPLE; i>=0; --i) { + blk = &inode->addr[i]; if (*blk == 0) continue; - if (blk == &inode->addr [TRIPLE]) - fs_triple_indirect_block_free (inode->fs, *blk); - else if (blk == &inode->addr [DOUBLE]) - fs_double_indirect_block_free (inode->fs, *blk); - else if (blk == &inode->addr [SINGLE]) - fs_indirect_block_free (inode->fs, *blk); - else + if (i == TRIPLE) { + if (! fs_triple_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) + break; + } else if (i == DOUBLE) { + if (! fs_double_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4))) + break; + } else if (i == SINGLE) { + if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) + break; + } else { + if (i * BSDFS_BSIZE < size) + break; fs_block_free (inode->fs, *blk); + } *blk = 0; } - inode->size = 0; + inode->size = size; inode->dirty = 1; } @@ -743,7 +754,7 @@ delete_file: inode->dirty = 1; inode->nlink--; if (inode->nlink <= 0) { - fs_inode_truncate (inode); + fs_inode_truncate (inode, 0); fs_inode_clear (inode); if (inode->fs->ninode < NICINOD) { inode->fs->inode [inode->fs->ninode++] = dirent.inum; diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 1d05a9b..8471ede 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -173,6 +173,12 @@ int op_open(const char *path, struct fuse_file_info *fi) return -ENOENT; } + if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot open special files. */ + file.inode.mode = 0; + return -ENXIO; + } + if (fi->flags & O_APPEND) { file.offset = file.inode.size; } From d6e558bea0587bca1381491a90cc5733eb82030f Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 18 Jul 2014 00:13:27 -0700 Subject: [PATCH 23/40] Fsutil mount: added truncate, mkdir, rmdir, link and unlink calls. --- tools/fsutil/mount.c | 368 +++++++++++++++++++++++++++---------------- 1 file changed, 231 insertions(+), 137 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 8471ede..165bb93 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -113,8 +113,7 @@ int op_getattr(const char *path, struct stat *statbuf) fs_t *fs = fuse_get_context()->private_data; fs_inode_t inode; - printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", - path, statbuf); + printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { printlog("--- search failed\n"); @@ -136,12 +135,8 @@ int op_getattr(const char *path, struct stat *statbuf) int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { printlog("--- op_fgetattr(path=\"%s\", statbuf=%p, fi=%p)\n", - path, statbuf, fi); + path, statbuf, fi); - // On FreeBSD, trying to do anything with the mountpoint ends up - // opening it, and then using the FD for an fgetattr. So in the - // special case of a path of "/", I need to do a getattr on the - // underlying root directory instead of doing the fgetattr(). if (strcmp(path, "/") == 0) return op_getattr(path, statbuf); @@ -166,7 +161,7 @@ int op_open(const char *path, struct fuse_file_info *fi) int write_flag = (fi->flags & O_ACCMODE) != O_RDONLY; printlog("--- op_open(path=\"%s\", fi=%p) flags=%#x \n", - path, fi, fi->flags); + path, fi, fi->flags); if (! fs_file_open (fs, &file, path, write_flag)) { printlog("--- open failed\n"); @@ -200,7 +195,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) fs_t *fs = fuse_get_context()->private_data; printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", - path, mode, fi); + path, mode, fi); file.inode.mode = 0; if (! fs_file_create (fs, &file, path, mode & 07777)) { @@ -209,6 +204,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) return -EISDIR; return -EIO; } + file.inode.mtime = time(0); return 0; } @@ -225,7 +221,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); + path, buf, size, offset, fi); if (offset >= file.inode.size) return 0; @@ -253,13 +249,14 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", - path, buf, size, offset, fi); + path, buf, size, offset, fi); file.offset = offset; if (! fs_file_write (&file, (unsigned char*) buf, size)) { printlog("--- read failed\n"); return -EIO; } + file.inode.mtime = time(0); return size; } @@ -278,8 +275,7 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, */ int op_release(const char *path, struct fuse_file_info *fi) { - printlog("--- op_release(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_release(path=\"%s\", fi=%p)\n", path, fi); if (file.inode.mode == 0) return -EBADF; @@ -289,6 +285,212 @@ int op_release(const char *path, struct fuse_file_info *fi) return 0; } +/* + * Change the size of a file + */ +int op_truncate(const char *path, off_t newsize) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_file_t f; + + printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", path, newsize); + + if (! fs_file_open (fs, &f, path, 1)) { + printlog("--- open failed\n"); + return -ENOENT; + } + + if ((f.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&f.inode, newsize); + f.inode.mtime = time(0); + fs_file_close (&f); + return 0; +} + +/* + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + */ +int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) +{ + printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", + path, offset, fi); + + if (! file.writable) + return -EACCES; + + if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + /* Cannot truncate special files. */ + return -EINVAL; + } + fs_inode_truncate (&file.inode, offset); + file.inode.mtime = time(0); + fs_file_close (&file); + return 0; +} + +/* + * Remove a file + */ +int op_unlink(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("op_unlink(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((file.inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot unlink directories. */ + return -EISDIR; + } + + /* Delete file. */ + if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + printlog("--- delete failed\n"); + return -EIO; + } + return 0; +} + +/* + * Remove a directory + */ +int op_rmdir(const char *path) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("op_rmdir(path=\"%s\")\n", path); + + /* Get the file type. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- search failed\n"); + return -ENOENT; + } + if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + /* Cannot remove files. */ + return -ENOTDIR; + } + if (inode.nlink > 2) { + /* Cannot remove non-empty directories. */ + return -ENOTEMPTY; + } + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Delete directory. */ + inode.nlink -= 1; + if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + printlog("--- delete failed\n"); + return -EIO; + } + + /* Decrease a parent's link counter. */ + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + ++parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a directory + */ +int op_mkdir(const char *path, mode_t mode) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; + + printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", path, mode); + + /* Open parent directory. */ + strcpy (buf, path); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + printlog("--- parent not found\n"); + return -ENOENT; + } + + /* Create directory. */ + int done = fs_inode_by_name (fs, &dir, path, 1, INODE_MODE_FDIR | (mode & 07777)); + if (! done) { + printlog("--- cannot create dir inode\n"); + return -ENOENT; + } + if (done == 1) { + /* The directory already existed. */ + return -EEXIST; + } + fs_inode_save (&dir, 0); + + /* Make parent link '..' */ + strcpy (buf, path); + strcat (buf, "/.."); + if (! fs_inode_by_name (fs, &dir, buf, 3, parent.number)) { + printlog("--- dotdot link failed\n"); + return -EIO; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + printlog("--- cannot reopen parent\n"); + return -EIO; + } + ++parent.nlink; + fs_inode_save (&parent, 1); + return 0; +} + +/* + * Create a hard link to a file + */ +int op_link(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t source, target; + + printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Find source. */ + if (! fs_inode_by_name (fs, &source, path, 0, 0)) { + printlog("--- source not found\n"); + return -ENOENT; + } + + /* Create target link. */ + if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { + printlog("--- link failed\n"); + return -EIO; + } + return 0; +} + /* * Read the target of a symbolic link * @@ -305,7 +507,7 @@ int op_release(const char *path, struct fuse_file_info *fi) int op_readlink(const char *path, char *link, size_t size) { printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", - path, link, size); + path, link, size); //TODO //retstat = readlink(path, link, size - 1); @@ -328,7 +530,7 @@ int op_readlink(const char *path, char *link, size_t size) int op_mknod(const char *path, mode_t mode, dev_t dev) { printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", - path, mode, dev); + path, mode, dev); //TODO //if (S_ISREG(mode)) { @@ -352,54 +554,6 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) return 0; } -/* - * Create a directory - */ -int op_mkdir(const char *path, mode_t mode) -{ - printlog("--- op_mkdir(path=\"%s\", mode=0%3o)\n", - path, mode); - - //TODO - //retstat = mkdir(path, mode); - //if (retstat < 0) - // retstat = print_errno("op_mkdir mkdir"); - - return 0; -} - -/* - * Remove a file - */ -int op_unlink(const char *path) -{ - printlog("op_unlink(path=\"%s\")\n", - path); - - //TODO - //retstat = unlink(path); - //if (retstat < 0) - // retstat = print_errno("op_unlink unlink"); - - return 0; -} - -/* - * Remove a directory - */ -int op_rmdir(const char *path) -{ - printlog("op_rmdir(path=\"%s\")\n", - path); - - //TODO - //retstat = rmdir(path); - //if (retstat < 0) - // retstat = print_errno("op_rmdir rmdir"); - - return 0; -} - /* * Create a symbolic link * The parameters here are a little bit confusing, but do correspond @@ -409,8 +563,7 @@ int op_rmdir(const char *path) */ int op_symlink(const char *path, const char *link) { - printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", - path, link); + printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", path, link); //TODO //retstat = symlink(path, link); @@ -427,8 +580,7 @@ int op_symlink(const char *path, const char *link) */ int op_rename(const char *path, const char *newpath) { - printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", - path, newpath); + printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); //TODO //retstat = rename(path, newpath); @@ -438,29 +590,12 @@ int op_rename(const char *path, const char *newpath) return 0; } -/* - * Create a hard link to a file - */ -int op_link(const char *path, const char *newpath) -{ - printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", - path, newpath); - - //TODO - //retstat = link(path, newpath); - //if (retstat < 0) - // retstat = print_errno("op_link link"); - - return 0; -} - /* * Change the permission bits of a file */ int op_chmod(const char *path, mode_t mode) { - printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", - path, mode); + printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); //TODO //retstat = chmod(path, mode); @@ -475,8 +610,7 @@ int op_chmod(const char *path, mode_t mode) */ int op_chown(const char *path, uid_t uid, gid_t gid) { - printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", - path, uid, gid); + printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); //TODO //retstat = chown(path, uid, gid); @@ -486,29 +620,12 @@ int op_chown(const char *path, uid_t uid, gid_t gid) return 0; } -/* - * Change the size of a file - */ -int op_truncate(const char *path, off_t newsize) -{ - printlog("--- op_truncate(path=\"%s\", newsize=%lld)\n", - path, newsize); - - //TODO - //retstat = truncate(path, newsize); - //if (retstat < 0) - // print_errno("op_truncate truncate"); - - return 0; -} - /* * Change the access and/or modification times of a file */ int op_utime(const char *path, struct utimbuf *ubuf) { - printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", - path, ubuf); + printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); //TODO //retstat = utime(path, ubuf); @@ -525,8 +642,7 @@ int op_utime(const char *path, struct utimbuf *ubuf) */ int op_statfs(const char *path, struct statvfs *statv) { - printlog("--- op_statfs(path=\"%s\", statv=%p)\n", - path, statv); + printlog("--- op_statfs(path=\"%s\", statv=%p)\n", path, statv); // get stats for underlying filesystem //TODO @@ -574,7 +690,7 @@ int op_flush(const char *path, struct fuse_file_info *fi) int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) { printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", - path, datasync, fi); + path, datasync, fi); if (datasync == 0 && file.writable) { if (! fs_inode_save (&file.inode, 0)) @@ -591,8 +707,7 @@ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) */ int op_opendir(const char *path, struct fuse_file_info *fi) { - printlog("--- op_opendir(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_opendir(path=\"%s\", fi=%p)\n", path, fi); return 0; } @@ -629,7 +744,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset } dirent; printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", - path, buf, filler, offset, fi); + path, buf, filler, offset, fi); if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { printlog("--- cannot find path %s\n", path); @@ -668,8 +783,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset */ int op_releasedir(const char *path, struct fuse_file_info *fi) { - printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", - path, fi); + printlog("--- op_releasedir(path=\"%s\", fi=%p)\n", path, fi); return 0; } @@ -692,32 +806,12 @@ void op_destroy(void *userdata) */ int op_access(const char *path, int mask) { - printlog("--- op_access(path=\"%s\", mask=0%o)\n", - path, mask); + printlog("--- op_access(path=\"%s\", mask=0%o)\n", path, mask); /* Always permitted. */ return 0; } -/* - * Change the size of an open file - * - * This method is called instead of the truncate() method if the - * truncation was invoked from an ftruncate() system call. - */ -int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) -{ - printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", - path, offset, fi); - - //TODO - //retstat = ftruncate(fi->fh, offset); - //if (retstat < 0) - // retstat = print_errno("op_ftruncate ftruncate"); - - return 0; -} - static struct fuse_operations mount_ops = { .access = op_access, .chmod = op_chmod, @@ -760,10 +854,10 @@ int fs_mount(fs_t *fs, char *dirname) /* Invoke FUSE to mount the filesystem. */ ac = 0; av[ac++] = "fsutil"; - av[ac++] = "-f"; // foreground - av[ac++] = "-s"; // single-threaded + av[ac++] = "-f"; /* foreground */ + av[ac++] = "-s"; /* single-threaded */ if (verbose > 1) - av[ac++] = "-d"; // debug + av[ac++] = "-d"; /* debug */ av[ac++] = dirname; av[ac] = 0; ret = fuse_main(ac, av, &mount_ops, fs); From 3a789348da2f4625b9a41931ae3673507cd3fb56 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 18 Jul 2014 17:41:08 -0700 Subject: [PATCH 24/40] Fsutol mount: fixed rmdir call. --- tools/fsutil/mount.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 165bb93..40e96ac 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -205,6 +205,8 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) return -EIO; } file.inode.mtime = time(0); + file.inode.dirty = 1; + fs_file_close (&file); return 0; } @@ -257,6 +259,7 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, return -EIO; } file.inode.mtime = time(0); + file.inode.dirty = 1; return size; } @@ -306,6 +309,7 @@ int op_truncate(const char *path, off_t newsize) } fs_inode_truncate (&f.inode, newsize); f.inode.mtime = time(0); + file.inode.dirty = 1; fs_file_close (&f); return 0; } @@ -330,6 +334,7 @@ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) } fs_inode_truncate (&file.inode, offset); file.inode.mtime = time(0); + file.inode.dirty = 1; fs_file_close (&file); return 0; } @@ -359,6 +364,7 @@ int op_unlink(const char *path) printlog("--- delete failed\n"); return -EIO; } + fs_inode_save (&inode, 1); return 0; } @@ -399,19 +405,26 @@ int op_rmdir(const char *path) return -ENOENT; } - /* Delete directory. */ - inode.nlink -= 1; + /* Delete directory. + * Need to decrease a link count first. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- directory not found\n"); + return -ENOENT; + } + --inode.nlink; + fs_inode_save (&inode, 1); if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { printlog("--- delete failed\n"); return -EIO; } + fs_inode_save (&inode, 1); /* Decrease a parent's link counter. */ if (! fs_inode_get (fs, &parent, parent.number)) { printlog("--- cannot reopen parent\n"); return -EIO; } - ++parent.nlink; + --parent.nlink; fs_inode_save (&parent, 1); return 0; } @@ -769,6 +782,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset if (dirent.inum != 0) { //printlog("calling filler with name %s\n", name); + name[dirent.namlen] = 0; if (filler(buf, name, NULL, 0) != 0) { printlog(" ERROR op_readdir filler: buffer full"); return -ENOMEM; @@ -865,6 +879,8 @@ int fs_mount(fs_t *fs, char *dirname) perror ("fuse_main failed"); return -1; } + fs_sync (fs, 0); + fs_close (fs); printf ("\nFilesystem %s unmounted\n", dirname); return ret; } From 21babaf947a315d8ab0c9915f897fbfbcb0158d7 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 18 Jul 2014 19:07:51 -0700 Subject: [PATCH 25/40] Fsutil mount: added rename and mknod calls. --- tools/fsutil/mount.c | 134 +++++++++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 50 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 40e96ac..ececd10 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -496,6 +496,11 @@ int op_link(const char *path, const char *newpath) return -ENOENT; } + if ((source.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot link directories. */ + return -EPERM; + } + /* Create target link. */ if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { printlog("--- link failed\n"); @@ -504,6 +509,85 @@ int op_link(const char *path, const char *newpath) return 0; } +/* + * Rename a file + * + * Both path and newpath are fs-relative. + */ +int op_rename(const char *path, const char *newpath) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t source, target; + + printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); + + /* Find source and increase the link count. */ + if (! fs_inode_by_name (fs, &source, path, 0, 0)) { + printlog("--- source not found\n"); + return -ENOENT; + } + source.nlink++; + fs_inode_save (&source, 1); + + /* Create target link. */ + if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { + printlog("--- link failed\n"); + return -EIO; + } + + /* Delete the source. */ + if (! fs_inode_by_name (fs, &source, path, 2, 0)) { + printlog("--- delete failed\n"); + return -EIO; + } + fs_inode_save (&source, 1); + return 0; +} + +/* + * Create a file node. + */ +int op_mknod(const char *path, mode_t mode, dev_t dev) +{ + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", + path, mode, dev); + + /* Check if the file already exists. */ + if (fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- already exists\n"); + return -EEXIST; + } + + /* Encode a mode bitmask. */ + if (S_ISREG(mode)) { + mode = (mode & 07777) | INODE_MODE_FREG; + } else if (S_ISCHR(mode)) { + mode = (mode & 07777) | INODE_MODE_FCHR; + } else if (S_ISBLK(mode)) { + mode = (mode & 07777) | INODE_MODE_FBLK; + } else + return -EINVAL; + + /* Create the file. */ + if (! fs_inode_by_name (fs, &inode, path, 1, mode)) { + printlog("--- create failed\n"); + return -EIO; + } + if (S_ISCHR(mode) || S_ISBLK(mode)) { + inode.addr[1] = dev; + } + inode.mtime = time(0); + inode.dirty = 1; + if (! fs_inode_save (&inode, 0)) { + printlog("--- create failed\n"); + return -EIO; + } + return 0; +} + /* * Read the target of a symbolic link * @@ -534,39 +618,6 @@ int op_readlink(const char *path, char *link, size_t size) return 0; } -/* - * Create a file node - * - * There is no create() operation, mknod() will be called for - * creation of all non-directory, non-symlink nodes. - */ -int op_mknod(const char *path, mode_t mode, dev_t dev) -{ - printlog("--- op_mknod(path=\"%s\", mode=0%3o, dev=%lld)\n", - path, mode, dev); - - //TODO - //if (S_ISREG(mode)) { - // retstat = open(path, O_CREAT | O_EXCL | O_WRONLY, mode); - // if (retstat < 0) - // retstat = print_errno("op_mknod open"); - // else { - // retstat = close(retstat); - // if (retstat < 0) - // retstat = print_errno("op_mknod close"); - // } - //} else if (S_ISFIFO(mode)) { - // retstat = mkfifo(path, mode); - // if (retstat < 0) - // retstat = print_errno("op_mknod mkfifo"); - //} else { - // retstat = mknod(path, mode, dev); - // if (retstat < 0) - // retstat = print_errno("op_mknod mknod"); - //} - return 0; -} - /* * Create a symbolic link * The parameters here are a little bit confusing, but do correspond @@ -586,23 +637,6 @@ int op_symlink(const char *path, const char *link) return 0; } -/* - * Rename a file - * - * Both path and newpath are fs-relative. - */ -int op_rename(const char *path, const char *newpath) -{ - printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); - - //TODO - //retstat = rename(path, newpath); - //if (retstat < 0) - // retstat = print_errno("op_rename rename"); - - return 0; -} - /* * Change the permission bits of a file */ From 173efb822d505f70701c795e3cebca430710d6e3 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 19 Jul 2014 15:06:55 -0700 Subject: [PATCH 26/40] Fsutil mount: symlink() and readlink() calls completed. --- tools/fsutil/mount.c | 227 +++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 151 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index ececd10..364afee 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -103,10 +103,6 @@ static int getstat (fs_inode_t *inode, struct stat *statbuf) /* * Get file attributes. - * - * Similar to stat(). The 'st_dev' and 'st_blksize' fields are - * ignored. The 'st_ino' field is ignored except if the 'use_ino' - * mount option is given. */ int op_getattr(const char *path, struct stat *statbuf) { @@ -123,14 +119,7 @@ int op_getattr(const char *path, struct stat *statbuf) } /* - * Get attributes from an open file - * - * This method is called instead of the getattr() method if the - * file information is available. - * - * Currently this is only called after the create() method if that - * is implemented (see above). Later it may be called for - * invocations of fstat() too. + * Get attributes from an open file. */ int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { @@ -147,13 +136,7 @@ int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *f } /* - * File open operation - * - * No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC) - * will be passed to open(). Open should check if the operation - * is permitted for the given flags. Optionally open may also - * return an arbitrary filehandle in the fuse_file_info structure, - * which will be passed to all file operations. + * File open operation. */ int op_open(const char *path, struct fuse_file_info *fi) { @@ -181,14 +164,7 @@ int op_open(const char *path, struct fuse_file_info *fi) } /* - * Create and open a file - * - * If the file does not exist, first create it with the specified - * mode, and then open it. - * - * If this method is not implemented or under Linux kernel - * versions earlier than 2.6.15, the mknod() and open() methods - * will be called instead. + * Create and open a file. */ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) { @@ -211,14 +187,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) } /* - * Read data from an open file - * - * Read should return exactly the number of bytes requested except - * on EOF or error, otherwise the rest of the data will be - * substituted with zeroes. An exception to this is when the - * 'direct_io' mount option is specified, in which case the return - * value of the read system call will reflect the return value of - * this operation. + * Read data from an open file. */ int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { @@ -241,11 +210,7 @@ int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_ } /* - * Write data to an open file - * - * Write should return exactly the number of bytes requested - * except on error. An exception to this is when the 'direct_io' - * mount option is specified (see read operation). + * Write data to an open file. */ int op_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) @@ -264,17 +229,7 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, } /* - * Release an open file - * - * Release is called when there are no more references to an open - * file: all file descriptors are closed and all memory mappings - * are unmapped. - * - * For every open() call there will be exactly one release() call - * with the same flags and file descriptor. It is possible to - * have a file opened more than once, in which case only the last - * release will mean, that no more reads/writes will happen on the - * file. The return value of release is ignored. + * Release an open file. */ int op_release(const char *path, struct fuse_file_info *fi) { @@ -315,10 +270,7 @@ int op_truncate(const char *path, off_t newsize) } /* - * Change the size of an open file - * - * This method is called instead of the truncate() method if the - * truncation was invoked from an ftruncate() system call. + * Change the size of an open file. */ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) { @@ -340,14 +292,14 @@ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) } /* - * Remove a file + * Remove a file. */ int op_unlink(const char *path) { fs_t *fs = fuse_get_context()->private_data; fs_inode_t inode; - printlog("op_unlink(path=\"%s\")\n", path); + printlog("--- op_unlink(path=\"%s\")\n", path); /* Get the file type. */ if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { @@ -369,7 +321,7 @@ int op_unlink(const char *path) } /* - * Remove a directory + * Remove a directory. */ int op_rmdir(const char *path) { @@ -377,7 +329,7 @@ int op_rmdir(const char *path) fs_inode_t inode, parent; char buf [BSDFS_BSIZE], *p; - printlog("op_rmdir(path=\"%s\")\n", path); + printlog("--- op_rmdir(path=\"%s\")\n", path); /* Get the file type. */ if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { @@ -430,7 +382,7 @@ int op_rmdir(const char *path) } /* - * Create a directory + * Create a directory. */ int op_mkdir(const char *path, mode_t mode) { @@ -481,7 +433,7 @@ int op_mkdir(const char *path, mode_t mode) } /* - * Create a hard link to a file + * Create a hard link to a file. */ int op_link(const char *path, const char *newpath) { @@ -510,9 +462,7 @@ int op_link(const char *path, const char *newpath) } /* - * Rename a file - * - * Both path and newpath are fs-relative. + * Rename a file. */ int op_rename(const char *path, const char *newpath) { @@ -589,56 +539,76 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) } /* - * Read the target of a symbolic link - * - * The buffer should be filled with a null terminated string. The - * buffer size argument includes the space for the terminating - * null character. If the linkname is too long to fit in the - * buffer, it should be truncated. The return value should be 0 - * for success. + * Read the target of a symbolic link. */ -// Note the system readlink() will truncate and lose the terminating -// null. So, the size passed to to the system readlink() must be one -// less than the size passed to op_readlink() -// op_readlink() code by Bernardo F Costa (thanks!) int op_readlink(const char *path, char *link, size_t size) { - printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + + printlog("--- op_readlink(path=\"%s\", link=\"%s\", size=%d)\n", path, link, size); - //TODO - //retstat = readlink(path, link, size - 1); - //if (retstat < 0) - // retstat = print_errno("op_readlink readlink"); - //else { - // link[retstat] = '\0'; - // retstat = 0; - //} + /* Open the file. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- file not found\n"); + return -ENOENT; + } + if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FLNK) + return -EINVAL; + + /* Leave one byte for the terminating null. */ + if (size > inode.size + 1) + size = inode.size + 1; + if (! fs_inode_read (&inode, 0, (unsigned char*)link, size-1)) { + printlog("--- read failed\n"); + return -EIO; + } + link[size-1] = 0; return 0; } /* - * Create a symbolic link - * The parameters here are a little bit confusing, but do correspond - * to the symlink() system call. The 'path' is where the link points, - * while the 'link' is the link itself. So we need to leave the path - * unaltered, but insert the link into the mounted directory. + * Create a symbolic link. */ -int op_symlink(const char *path, const char *link) +int op_symlink(const char *path, const char *newpath) { - printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", path, link); + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + int len, mode; - //TODO - //retstat = symlink(path, link); - //if (retstat < 0) - // retstat = print_errno("op_symlink symlink"); + printlog("--- op_symlink(path=\"%s\", newpath=\"%s\")\n", path, newpath); + /* Check if the file already exists. */ + if (fs_inode_by_name (fs, &inode, newpath, 0, 0)) { + printlog("--- already exists\n"); + return -EEXIST; + } + + mode = 0777 | INODE_MODE_FLNK; + if (! fs_inode_by_name (fs, &inode, newpath, 1, mode)) { + printlog("--- create failed\n"); + return -EIO; + } + fs_inode_save (&inode, 0); + + len = strlen (path); + if (! fs_inode_write (&inode, 0, (unsigned char*)path, len)) { + printlog("--- write failed\n"); + return -EIO; + } + inode.mtime = time(0); + inode.dirty = 1; + if (! fs_inode_save (&inode, 0)) { + printlog("--- create failed\n"); + return -EIO; + } return 0; } /* - * Change the permission bits of a file + * Change the permission bits of a file. */ int op_chmod(const char *path, mode_t mode) { @@ -653,7 +623,7 @@ int op_chmod(const char *path, mode_t mode) } /* - * Change the owner and group of a file + * Change the owner and group of a file. */ int op_chown(const char *path, uid_t uid, gid_t gid) { @@ -668,7 +638,7 @@ int op_chown(const char *path, uid_t uid, gid_t gid) } /* - * Change the access and/or modification times of a file + * Change the access and/or modification times of a file. */ int op_utime(const char *path, struct utimbuf *ubuf) { @@ -683,7 +653,7 @@ int op_utime(const char *path, struct utimbuf *ubuf) } /* - * Get file system statistics + * Get file system statistics. * * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored */ @@ -701,26 +671,7 @@ int op_statfs(const char *path, struct statvfs *statv) } /* - * Possibly flush cached data - * - * BIG NOTE: This is not equivalent to fsync(). It's not a - * request to sync dirty data. - * - * Flush is called on each close() of a file descriptor. So if a - * filesystem wants to return write errors in close() and the file - * has cached dirty data, this is a good place to write back data - * and return any errors. Since many applications ignore close() - * errors this is not always useful. - * - * NOTE: The flush() method may be called more than once for each - * open(). This happens if more than one file descriptor refers - * to an opened file due to dup(), dup2() or fork() calls. It is - * not possible to determine if a flush is final, so each flush - * should be treated equally. Multiple write-flush sequences are - * relatively rare, so this shouldn't be a problem. - * - * Filesystems shouldn't assume that flush will always be called - * after some writes, or that if will be called at all. + * Possibly flush cached data. */ int op_flush(const char *path, struct fuse_file_info *fi) { @@ -729,8 +680,7 @@ int op_flush(const char *path, struct fuse_file_info *fi) } /* - * Synchronize file contents - * + * Synchronize file contents. * If the datasync parameter is non-zero, then only the user data * should be flushed, not the meta data. */ @@ -747,10 +697,7 @@ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) } /* - * Open directory - * - * This method should check if the open operation is permitted for - * this directory + * Open directory. */ int op_opendir(const char *path, struct fuse_file_info *fi) { @@ -759,24 +706,7 @@ int op_opendir(const char *path, struct fuse_file_info *fi) } /* - * Read directory - * - * This supersedes the old getdir() interface. New applications - * should use this. - * - * The filesystem may choose between two modes of operation: - * - * 1) The readdir implementation ignores the offset parameter, and - * passes zero to the filler function's offset. The filler - * function will not return '1' (unless an error happens), so the - * whole directory is read in a single readdir operation. This - * works just like the old getdir() method. - * - * 2) The readdir implementation keeps track of the offsets of the - * directory entries. It uses the offset parameter and always - * passes non-zero offset to the filler function. When the buffer - * is full (or an error happens) the filler function will return - * '1'. + * Read directory. */ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) @@ -827,7 +757,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset } /* - * Release directory + * Release directory. */ int op_releasedir(const char *path, struct fuse_file_info *fi) { @@ -836,8 +766,7 @@ int op_releasedir(const char *path, struct fuse_file_info *fi) } /* - * Clean up filesystem - * + * Clean up filesystem. * Called on filesystem exit. */ void op_destroy(void *userdata) @@ -846,11 +775,7 @@ void op_destroy(void *userdata) } /* - * Check file access permissions - * - * This will be called for the access() system call. If the - * 'default_permissions' mount option is given, this method is not - * called. + * Check file access permissions. */ int op_access(const char *path, int mask) { From 61ce1693285cc901ce215bf71114b57d5bb95167 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sun, 20 Jul 2014 16:57:36 -0700 Subject: [PATCH 27/40] Fsutil mount complete. --- tools/fsutil/mount.c | 62 ++++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 364afee..f96bab6 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -612,13 +612,22 @@ int op_symlink(const char *path, const char *newpath) */ int op_chmod(const char *path, mode_t mode) { + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); - //TODO - //retstat = chmod(path, mode); - //if (retstat < 0) - // retstat = print_errno("op_chmod chmod"); + /* Open the file. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- file not found\n"); + return -ENOENT; + } + /* Modify the access mode. */ + inode.mode &= ~07777; + inode.mode |= mode; + inode.dirty = 1; + fs_inode_save (&inode, 0); return 0; } @@ -627,13 +636,22 @@ int op_chmod(const char *path, mode_t mode) */ int op_chown(const char *path, uid_t uid, gid_t gid) { + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); - //TODO - //retstat = chown(path, uid, gid); - //if (retstat < 0) - // retstat = print_errno("op_chown chown"); + /* Open the file. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- file not found\n"); + return -ENOENT; + } + /* Modify the owner and group. */ + inode.uid = uid; + inode.gid = gid; + inode.dirty = 1; + fs_inode_save (&inode, 0); return 0; } @@ -642,13 +660,22 @@ int op_chown(const char *path, uid_t uid, gid_t gid) */ int op_utime(const char *path, struct utimbuf *ubuf) { + fs_t *fs = fuse_get_context()->private_data; + fs_inode_t inode; + printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); - //TODO - //retstat = utime(path, ubuf); - //if (retstat < 0) - // retstat = print_errno("op_utime utime"); + /* Open the file. */ + if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + printlog("--- file not found\n"); + return -ENOENT; + } + /* Modify the access and modification times. */ + inode.atime = ubuf->actime; + inode.mtime = ubuf->modtime; + inode.dirty = 1; + fs_inode_save (&inode, 0); return 0; } @@ -659,14 +686,15 @@ int op_utime(const char *path, struct utimbuf *ubuf) */ int op_statfs(const char *path, struct statvfs *statv) { + fs_dirent_t dirent; + printlog("--- op_statfs(path=\"%s\", statv=%p)\n", path, statv); - // get stats for underlying filesystem - //TODO - //retstat = statvfs(path, statv); - //if (retstat < 0) - // retstat = print_errno("op_statfs statvfs"); + /* The maximum length in bytes of a file name on this file system. */ + statv->f_namemax = sizeof(dirent.name) - 1; + /* The preferred length of I/O requests for files on this file system. */ + statv->f_bsize = BSDFS_BSIZE; return 0; } From 2293493bfd5dbeeb02e851151168695298814117 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sun, 20 Jul 2014 17:23:57 -0700 Subject: [PATCH 28/40] Fixed bugs in fsutil. --- sys/pic32/exception.c | 10 +++++----- tools/fsutil/fsutil.c | 3 +++ tools/fsutil/inode.c | 1 - tools/fsutil/mount.c | 13 +++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/sys/pic32/exception.c b/sys/pic32/exception.c index 2d70c7d..5434a85 100644 --- a/sys/pic32/exception.c +++ b/sys/pic32/exception.c @@ -158,7 +158,7 @@ dumpregs (frame) printf( "*******STACK DUMP START*************\n"); printf( "frame = %8x\n", frame ); printf( "stack data\n" ); - while( p <= stacktop ) + while( p <= stacktop ) { printf( " %8x", *p++ ); if( p <= stacktop ) printf( " %8x", *p++ ); @@ -343,14 +343,14 @@ exception (frame) mips_write_c0_register (C0_COMPARE, 0, c); } while ((int) (c - (unsigned)mips_read_c0_register (C0_COUNT, 0)) < 0); hardclock ((caddr_t) frame [FRAME_PC], status); - + #ifdef POWER_ENABLED power_switch_check(); #endif #ifdef UARTUSB_ENABLED /* Poll USB on every timer tick. */ - usbintr(0); + usbintr(0); #endif break; #ifdef UART1_ENABLED @@ -389,7 +389,7 @@ exception (frame) #ifdef UARTUSB_ENABLED case PIC32_VECT_USB: /* USB */ IFSCLR(1) = 1 << (PIC32_IRQ_USB - 32); - usbintr(0); + usbintr(0); break; #endif @@ -418,7 +418,7 @@ exception (frame) if (sp < u.u_procp->p_daddr + u.u_dsize) { /* Process has trashed its stack; give it an illegal * instruction violation to halt it in its tracks. */ - panic ("unexpected exception 2"); + panic ("unexpected exception 2"); psig = SIGSEGV; break; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index c1b6887..20327b6 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -354,6 +355,7 @@ void add_device (fs_t *fs, char *name, char *spec) return; } dev.addr[1] = majr << 8 | minr; + time (&dev.mtime); fs_inode_save (&dev, 1); } @@ -408,6 +410,7 @@ void add_file (fs_t *fs, char *name) } } file.inode.mtime = st.st_mtime; + file.inode.dirty = 1; fs_file_close (&file); fclose (fd); } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index 418f953..d021cce 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -161,7 +161,6 @@ int fs_inode_save (fs_inode_t *inode, int force) BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; time (&inode->atime); - //time (&inode->mtime); if (! fs_seek (inode->fs, offset)) return 0; diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index f96bab6..bb8f0be 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -56,6 +56,11 @@ static void printlog(const char *format, ...) } } +static dev_t make_rdev(unsigned raw) +{ + return makedev (raw >> 8, raw & 0xff); +} + /* * Copy data to struct stat. */ @@ -66,7 +71,7 @@ static int getstat (fs_inode_t *inode, struct stat *statbuf) statbuf->st_nlink = inode->nlink; /* number of hard links */ statbuf->st_uid = inode->uid; /* user ID of owner */ statbuf->st_gid = inode->gid; /* group ID of owner */ - statbuf->st_rdev = 0; /* device ID (if special file) */ + statbuf->st_rdev = 0; /* device ID (if special file) */ statbuf->st_size = inode->size; /* total size, in bytes */ statbuf->st_blocks = inode->size >> 9; /* number of blocks allocated */ statbuf->st_atime = inode->atime; /* time of last access */ @@ -82,11 +87,11 @@ static int getstat (fs_inode_t *inode, struct stat *statbuf) break; case INODE_MODE_FCHR: /* character special */ statbuf->st_mode |= S_IFCHR; - statbuf->st_rdev = inode->addr[1]; + statbuf->st_rdev = make_rdev (inode->addr[1]); break; case INODE_MODE_FBLK: /* block special */ statbuf->st_mode |= S_IFBLK; - statbuf->st_rdev = inode->addr[1]; + statbuf->st_rdev = make_rdev (inode->addr[1]); break; case INODE_MODE_FLNK: /* symbolic link */ statbuf->st_mode |= S_IFLNK; @@ -527,7 +532,7 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) return -EIO; } if (S_ISCHR(mode) || S_ISBLK(mode)) { - inode.addr[1] = dev; + inode.addr[1] = major(dev) << 8 | minor(dev); } inode.mtime = time(0); inode.dirty = 1; From eb1fb36b6b56582babfb9ad621b68ddd2fdb129c Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 31 Jul 2014 17:46:24 -0700 Subject: [PATCH 29/40] Fsutil library: use names for inode ops. --- tools/fsutil/bsdfs.h | 9 +++++++- tools/fsutil/file.c | 4 ++-- tools/fsutil/fsutil.c | 8 +++---- tools/fsutil/inode.c | 15 +++++-------- tools/fsutil/mount.c | 51 +++++++++++++++++++++++-------------------- 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index 7b5954d..60be772 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -145,6 +145,13 @@ typedef struct { unsigned long offset; /* current i/o offset */ } fs_file_t; +typedef enum { + INODE_OP_LOOKUP, /* lookup inode by name */ + INODE_OP_CREATE, /* create new file */ + INODE_OP_DELETE, /* delete file */ + INODE_OP_LINK, /* make a link to a file */ +} fs_op_t; + int fs_seek (fs_t *fs, unsigned long offset); int fs_read8 (fs_t *fs, unsigned char *val); int fs_read16 (fs_t *fs, unsigned short *val); @@ -177,7 +184,7 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, unsigned char *data, unsigned long bytes); int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - int op, int mode); + fs_op_t op, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 3d0275e..8218edb 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -29,7 +29,7 @@ extern int verbose; int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { - if (! fs_inode_by_name (fs, &file->inode, name, 1, mode)) { + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { fprintf (stderr, "%s: inode open failed\n", name); return 0; } @@ -46,7 +46,7 @@ int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { - if (! fs_inode_by_name (fs, &file->inode, name, 0, 0)) { + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { fprintf (stderr, "%s: inode open failed\n", name); return 0; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 20327b6..39c386b 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -300,13 +300,13 @@ void add_directory (fs_t *fs, char *name) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { fprintf (stderr, "%s: cannot open directory\n", buf); return; } /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, name, 1, INODE_MODE_FDIR | 0777); + int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); if (! done) { fprintf (stderr, "%s: directory inode create failed\n", name); return; @@ -320,7 +320,7 @@ void add_directory (fs_t *fs, char *name) /* Make parent link '..' */ strcpy (buf, name); strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, 3, parent.number)) { + if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { fprintf (stderr, "%s: dotdot link failed\n", name); return; } @@ -349,7 +349,7 @@ void add_device (fs_t *fs, char *name, char *spec) fprintf (stderr, "expected c: or b:\n"); return; } - if (! fs_inode_by_name (fs, &dev, name, 1, 0666 | + if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { fprintf (stderr, "%s: device inode create failed\n", name); return; diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index d021cce..ec9d88b 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -551,13 +551,8 @@ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) * Return 1 when the inode was found. * Return 2 when the inode was created/deleted/linked. */ -#define LOOKUP 0 /* perform name lookup only */ -#define CREATE 1 /* setup for file creation */ -#define DELETE 2 /* setup for file deletion */ -#define LINK 3 /* setup for link */ - int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - int op, int mode) + fs_op_t op, int mode) { fs_inode_t dir; int c, namlen, reclen; @@ -577,7 +572,7 @@ int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, c = *name++; while (c == '/') c = *name++; - if (! c && op != LOOKUP) { + if (! c && op != INODE_OP_LOOKUP) { /* Cannot write or delete root directory. */ return 0; } @@ -631,7 +626,7 @@ cloop: /* Here a component matched in a directory. * If there is more pathname, go back to * cloop, otherwise return. */ - if (op == DELETE && ! c) { + if (op == INODE_OP_DELETE && ! c) { goto delete_file; } if (! fs_inode_get (fs, &dir, dirent.inum)) { @@ -643,9 +638,9 @@ cloop: } /* If at the end of the directory, the search failed. * Report what is appropriate as per flag. */ - if (op == CREATE && ! c) + if (op == INODE_OP_CREATE && ! c) goto create_file; - if (op == LINK && ! c) + if (op == INODE_OP_LINK && ! c) goto create_link; return 0; diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index bb8f0be..9e451ad 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -116,7 +116,7 @@ int op_getattr(const char *path, struct stat *statbuf) printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- search failed\n"); return -ENOENT; } @@ -307,7 +307,7 @@ int op_unlink(const char *path) printlog("--- op_unlink(path=\"%s\")\n", path); /* Get the file type. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- search failed\n"); return -ENOENT; } @@ -317,7 +317,7 @@ int op_unlink(const char *path) } /* Delete file. */ - if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_DELETE, 0)) { printlog("--- delete failed\n"); return -EIO; } @@ -337,7 +337,7 @@ int op_rmdir(const char *path) printlog("--- op_rmdir(path=\"%s\")\n", path); /* Get the file type. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- search failed\n"); return -ENOENT; } @@ -357,20 +357,20 @@ int op_rmdir(const char *path) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { printlog("--- parent not found\n"); return -ENOENT; } /* Delete directory. * Need to decrease a link count first. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- directory not found\n"); return -ENOENT; } --inode.nlink; fs_inode_save (&inode, 1); - if (! fs_inode_by_name (fs, &inode, path, 2, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_DELETE, 0)) { printlog("--- delete failed\n"); return -EIO; } @@ -404,13 +404,15 @@ int op_mkdir(const char *path, mode_t mode) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, 0, 0)) { + if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { printlog("--- parent not found\n"); return -ENOENT; } /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, path, 1, INODE_MODE_FDIR | (mode & 07777)); + mode &= 07777; + mode |= INODE_MODE_FDIR; + int done = fs_inode_by_name (fs, &dir, path, INODE_OP_CREATE, mode); if (! done) { printlog("--- cannot create dir inode\n"); return -ENOENT; @@ -424,7 +426,7 @@ int op_mkdir(const char *path, mode_t mode) /* Make parent link '..' */ strcpy (buf, path); strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, 3, parent.number)) { + if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { printlog("--- dotdot link failed\n"); return -EIO; } @@ -448,7 +450,7 @@ int op_link(const char *path, const char *newpath) printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Find source. */ - if (! fs_inode_by_name (fs, &source, path, 0, 0)) { + if (! fs_inode_by_name (fs, &source, path, INODE_OP_LOOKUP, 0)) { printlog("--- source not found\n"); return -ENOENT; } @@ -459,7 +461,7 @@ int op_link(const char *path, const char *newpath) } /* Create target link. */ - if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { + if (! fs_inode_by_name (fs, &target, newpath, INODE_OP_LINK, source.number)) { printlog("--- link failed\n"); return -EIO; } @@ -477,7 +479,7 @@ int op_rename(const char *path, const char *newpath) printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Find source and increase the link count. */ - if (! fs_inode_by_name (fs, &source, path, 0, 0)) { + if (! fs_inode_by_name (fs, &source, path, INODE_OP_LOOKUP, 0)) { printlog("--- source not found\n"); return -ENOENT; } @@ -485,13 +487,13 @@ int op_rename(const char *path, const char *newpath) fs_inode_save (&source, 1); /* Create target link. */ - if (! fs_inode_by_name (fs, &target, newpath, 3, source.number)) { + if (! fs_inode_by_name (fs, &target, newpath, INODE_OP_LINK, source.number)) { printlog("--- link failed\n"); return -EIO; } /* Delete the source. */ - if (! fs_inode_by_name (fs, &source, path, 2, 0)) { + if (! fs_inode_by_name (fs, &source, path, INODE_OP_DELETE, 0)) { printlog("--- delete failed\n"); return -EIO; } @@ -511,7 +513,7 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) path, mode, dev); /* Check if the file already exists. */ - if (fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- already exists\n"); return -EEXIST; } @@ -527,7 +529,7 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) return -EINVAL; /* Create the file. */ - if (! fs_inode_by_name (fs, &inode, path, 1, mode)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_CREATE, mode)) { printlog("--- create failed\n"); return -EIO; } @@ -555,7 +557,7 @@ int op_readlink(const char *path, char *link, size_t size) path, link, size); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- file not found\n"); return -ENOENT; } @@ -586,13 +588,14 @@ int op_symlink(const char *path, const char *newpath) printlog("--- op_symlink(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Check if the file already exists. */ - if (fs_inode_by_name (fs, &inode, newpath, 0, 0)) { + if (fs_inode_by_name (fs, &inode, newpath, INODE_OP_LOOKUP, 0)) { printlog("--- already exists\n"); return -EEXIST; } + /* Create symlink. */ mode = 0777 | INODE_MODE_FLNK; - if (! fs_inode_by_name (fs, &inode, newpath, 1, mode)) { + if (! fs_inode_by_name (fs, &inode, newpath, INODE_OP_CREATE, mode)) { printlog("--- create failed\n"); return -EIO; } @@ -623,7 +626,7 @@ int op_chmod(const char *path, mode_t mode) printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- file not found\n"); return -ENOENT; } @@ -647,7 +650,7 @@ int op_chown(const char *path, uid_t uid, gid_t gid) printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- file not found\n"); return -ENOENT; } @@ -671,7 +674,7 @@ int op_utime(const char *path, struct utimbuf *ubuf) printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, 0, 0)) { + if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { printlog("--- file not found\n"); return -ENOENT; } @@ -756,7 +759,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", path, buf, filler, offset, fi); - if (! fs_inode_by_name (fs, &dir, path, 0, 0)) { + if (! fs_inode_by_name (fs, &dir, path, INODE_OP_LOOKUP, 0)) { printlog("--- cannot find path %s\n", path); return -ENOENT; } From 4d8233582a1957c4eab84e41797dee572a4e0ed5 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 31 Jul 2014 18:16:39 -0700 Subject: [PATCH 30/40] Fsutil: added --manifest option. --- tools/fsutil/bsdfs.h | 8 +++---- tools/fsutil/fsutil.c | 52 ++++++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index 60be772..e2d77d5 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -146,10 +146,10 @@ typedef struct { } fs_file_t; typedef enum { - INODE_OP_LOOKUP, /* lookup inode by name */ - INODE_OP_CREATE, /* create new file */ - INODE_OP_DELETE, /* delete file */ - INODE_OP_LINK, /* make a link to a file */ + INODE_OP_LOOKUP, /* lookup inode by name */ + INODE_OP_CREATE, /* create new file */ + INODE_OP_DELETE, /* delete file */ + INODE_OP_LINK, /* make a link to a file */ } fs_op_t; int fs_seek (fs_t *fs, unsigned long offset); diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 39c386b..7fdfb8c 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -59,6 +59,7 @@ static struct option program_options[] = { { "mount", no_argument, 0, 'm' }, { "new", required_argument, 0, 'n' }, { "swap", required_argument, 0, 's' }, + { "manifest", required_argument, 0, 'M' }, { 0 } }; @@ -77,20 +78,22 @@ static void print_help (char *progname) printf (" %s --add filesys.img files...\n", progname); printf (" %s --extract filesys.img\n", progname); printf (" %s --check [--fix] filesys.img\n", progname); - printf (" %s --new=kbytes [--swap=kbytes] filesys.img\n", progname); + printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); printf (" %s --mount filesys.img dir\n", progname); printf ("\n"); printf ("Options:\n"); - printf (" -a, --add Add files to filesystem.\n"); - printf (" -x, --extract Extract all files.\n"); - printf (" -c, --check Check filesystem, use -c -f to fix.\n"); - printf (" -f, --fix Fix bugs in filesystem.\n"); - printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); - printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); - printf (" -m, --mount Mount the filesystem.\n"); - printf (" -v, --verbose Be verbose.\n"); - printf (" -V, --version Print version information and then exit.\n"); - printf (" -h, --help Print this message.\n"); + printf (" -a, --add Add files to filesystem.\n"); + printf (" -x, --extract Extract all files.\n"); + printf (" -c, --check Check filesystem, use -c -f to fix.\n"); + printf (" -f, --fix Fix bugs in filesystem.\n"); + printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); + printf (" Add files from specified directory (optional)\n"); + printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); + printf (" -M file, --manifest=file List of files and attributes to create.\n"); + printf (" -m, --mount Mount the filesystem.\n"); + printf (" -v, --verbose Be verbose.\n"); + printf (" -V, --version Print version information and then exit.\n"); + printf (" -h, --help Print this message.\n"); printf ("\n"); printf ("Report bugs to \"%s\".\n", program_bug_address); } @@ -415,14 +418,26 @@ void add_file (fs_t *fs, char *name) fclose (fd); } +/* + * Add the contents from the specified directory. + * Use the optional manifest file. + */ +void add_contents (fs_t *fs, const char *dirname, const char *manifest) +{ + printf ("TODO: add contents from directory '%s'\n", dirname); + if (manifest) + printf ("TODO: use manifest '%s'\n", manifest); +} + int main (int argc, char **argv) { int i, key; fs_t fs; fs_inode_t inode; + const char *manifest = 0; for (;;) { - key = getopt_long (argc, argv, "vaxmn:cfs:", + key = getopt_long (argc, argv, "vaxmMn:cfs:", program_options, 0); if (key == -1) break; @@ -452,6 +467,9 @@ int main (int argc, char **argv) case 's': swap_kbytes = strtol (optarg, 0, 0); break; + case 'M': + manifest = optarg; + break; case 'V': printf ("%s\n", program_version); return 0; @@ -464,7 +482,9 @@ int main (int argc, char **argv) } } i = optind; - if ((! add && ! mount && i != argc-1) || (add && i >= argc) || + if ((! add && ! mount && ! newfs && i != argc-1) || + (add && i >= argc) || + (newfs && i != argc-1 && i != argc-2) || (mount && i != argc-2) || (extract + newfs + check + add + mount > 1) || (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { @@ -479,6 +499,12 @@ int main (int argc, char **argv) return -1; } printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); + + if (i == argc-2) { + /* Add the contents from the specified directory. + * Use the optional manifest file. */ + add_contents (&fs, argv[i+1], manifest); + } fs_close (&fs); return 0; } From c2b3647d5e1f8649fb831325829aa702ae6d0ae8 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 31 Jul 2014 18:37:15 -0700 Subject: [PATCH 31/40] Fsutil: sources reformatted to 4-space indents. --- tools/fsutil/block.c | 238 +++---- tools/fsutil/bsdfs.h | 186 ++--- tools/fsutil/check.c | 1420 ++++++++++++++++++------------------- tools/fsutil/create.c | 608 ++++++++-------- tools/fsutil/file.c | 96 +-- tools/fsutil/fsutil.c | 863 +++++++++++----------- tools/fsutil/inode.c | 1340 +++++++++++++++++----------------- tools/fsutil/superblock.c | 462 ++++++------ 8 files changed, 2609 insertions(+), 2604 deletions(-) diff --git a/tools/fsutil/block.c b/tools/fsutil/block.c index c1a880f..0606c58 100644 --- a/tools/fsutil/block.c +++ b/tools/fsutil/block.c @@ -28,29 +28,29 @@ extern int verbose; int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("read block %d\n", bnum); - if (bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_read (fs, data, BSDFS_BSIZE)) - return 0; - return 1; + if (verbose > 3) + printf ("read block %d\n", bnum); + if (bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_read (fs, data, BSDFS_BSIZE)) + return 0; + return 1; } int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) { - if (verbose > 3) - printf ("write block %d\n", bnum); - if (! fs->writable || bnum < fs->isize) - return 0; - if (! fs_seek (fs, bnum * BSDFS_BSIZE)) - return 0; - if (! fs_write (fs, data, BSDFS_BSIZE)) - return 0; - fs->modified = 1; - return 1; + if (verbose > 3) + printf ("write block %d\n", bnum); + if (! fs->writable || bnum < fs->isize) + return 0; + if (! fs_seek (fs, bnum * BSDFS_BSIZE)) + return 0; + if (! fs_write (fs, data, BSDFS_BSIZE)) + return 0; + fs->modified = 1; + return 1; } /* @@ -58,27 +58,27 @@ int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data) */ int fs_block_free (fs_t *fs, unsigned int bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; - if (verbose > 1) - printf ("free block %d, total %d\n", bno, fs->nfree); - if (fs->nfree >= NICFREE) { - buf[0] = fs->nfree; - for (i=0; ifree[i]; - if (! fs_write_block (fs, bno, (unsigned char*) buf)) { - fprintf (stderr, "block_free: write error at block %d\n", bno); - return 0; - } - fs->nfree = 0; - } - fs->free [fs->nfree] = bno; - fs->nfree++; - fs->dirty = 1; - if (bno) /* Count total free blocks. */ - ++fs->tfree; - return 1; + if (verbose > 1) + printf ("free block %d, total %d\n", bno, fs->nfree); + if (fs->nfree >= NICFREE) { + buf[0] = fs->nfree; + for (i=0; ifree[i]; + if (! fs_write_block (fs, bno, (unsigned char*) buf)) { + fprintf (stderr, "block_free: write error at block %d\n", bno); + return 0; + } + fs->nfree = 0; + } + fs->free [fs->nfree] = bno; + fs->nfree++; + fs->dirty = 1; + if (bno) /* Count total free blocks. */ + ++fs->tfree; + return 1; } /* @@ -86,26 +86,26 @@ int fs_block_free (fs_t *fs, unsigned int bno) */ int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_block_free (fs, nb); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_block_free (fs, nb); + } + fs_block_free (fs, bno); + return 1; } /* @@ -113,27 +113,27 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 * BSDFS_BSIZE/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_indirect_block_free (fs, nb, - nblk - i/4 * BSDFS_BSIZE/4); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* @@ -141,27 +141,27 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) { - unsigned nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned nb; + unsigned char data [BSDFS_BSIZE]; + int i; - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "inode_clear: read error at block %d\n", bno); - return 0; - } - for (i=BSDFS_BSIZE-4; i>=0; i-=4) { - if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { - /* Truncate up to required size. */ - return 0; - } - nb = data [i+3] << 24 | data [i+2] << 16 | - data [i+1] << 8 | data [i]; - if (nb) - fs_double_indirect_block_free (fs, nb, - nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); - } - fs_block_free (fs, bno); - return 1; + if (! fs_read_block (fs, bno, data)) { + fprintf (stderr, "inode_clear: read error at block %d\n", bno); + return 0; + } + for (i=BSDFS_BSIZE-4; i>=0; i-=4) { + if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) { + /* Truncate up to required size. */ + return 0; + } + nb = data [i+3] << 24 | data [i+2] << 16 | + data [i+1] << 8 | data [i]; + if (nb) + fs_double_indirect_block_free (fs, nb, + nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4); + } + fs_block_free (fs, bno); + return 1; } /* @@ -169,26 +169,26 @@ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk) */ int fs_block_alloc (fs_t *fs, unsigned int *bno) { - int i; - unsigned buf [BSDFS_BSIZE / 4]; + int i; + unsigned buf [BSDFS_BSIZE / 4]; again: - if (fs->nfree == 0) - return 0; - fs->nfree--; - --fs->tfree; /* Count total free blocks. */ - *bno = fs->free [fs->nfree]; - if (verbose) - printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); - fs->free [fs->nfree] = 0; - fs->dirty = 1; - if (fs->nfree <= 0) { - if (! fs_read_block (fs, *bno, (unsigned char*) buf)) - return 0; - fs->nfree = buf[0]; - for (i=0; ifree[i] = buf[i+1]; - } - if (*bno == 0) - goto again; - return 1; + if (fs->nfree == 0) + return 0; + fs->nfree--; + --fs->tfree; /* Count total free blocks. */ + *bno = fs->free [fs->nfree]; + if (verbose) + printf ("allocate new block %d from slot %d\n", *bno, fs->nfree); + fs->free [fs->nfree] = 0; + fs->dirty = 1; + if (fs->nfree <= 0) { + if (! fs_read_block (fs, *bno, (unsigned char*) buf)) + return 0; + fs->nfree = buf[0]; + for (i=0; ifree[i] = buf[i+1]; + } + if (*bno == 0) + goto again; + return 1; } diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index e2d77d5..bd54e8b 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -21,135 +21,135 @@ * arising out of or in connection with the use or performance of * this software. */ -#define BSDFS_BSIZE 1024 /* block size */ -#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ -#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ -#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ -#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ +#define BSDFS_BSIZE 1024 /* block size */ +#define BSDFS_ROOT_INODE 2 /* root directory in inode 2 */ +#define BSDFS_LOSTFOUND_INODE 3 /* lost+found directory in inode 3 */ +#define BSDFS_SWAP_INODE 4 /* swap file in inode 4 */ +#define BSDFS_INODES_PER_BLOCK 16 /* inodes per block */ -#define NICINOD 32 /* number of superblock inodes */ -#define NICFREE 200 /* number of superblock free blocks */ +#define NICINOD 32 /* number of superblock inodes */ +#define NICFREE 200 /* number of superblock free blocks */ /* * 28 of the di_addr address bytes are used; 7 addresses of 4 * bytes each: 4 direct (4Kb directly accessible) and 3 indirect. */ -#define NDADDR 4 /* direct addresses in inode */ -#define NIADDR 3 /* indirect addresses in inode */ -#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ +#define NDADDR 4 /* direct addresses in inode */ +#define NIADDR 3 /* indirect addresses in inode */ +#define NADDR (NDADDR + NIADDR) /* total addresses in inode */ /* * NINDIR is the number of indirects in a file system block. */ -#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) -#define NSHIFT 8 /* log2(NINDIR) */ -#define NMASK 0377L /* NINDIR - 1 */ +#define NINDIR (DEV_BSIZE / sizeof(daddr_t)) +#define NSHIFT 8 /* log2(NINDIR) */ +#define NMASK 0377L /* NINDIR - 1 */ /* * The path name on which the file system is mounted is maintained * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in * the super block for this name. */ -#define MAXMNTLEN 28 +#define MAXMNTLEN 28 -#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) -#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) +#define FSMAGIC1 ('F' | 'S'<<8 | '<'<<16 | '<'<<24) +#define FSMAGIC2 ('>' | '>'<<8 | 'F'<<16 | 'S'<<24) typedef struct { - const char *filename; - int fd; - unsigned long seek; - int writable; - int dirty; /* sync needed */ - int modified; /* write_block was called */ + const char *filename; + int fd; + unsigned long seek; + int writable; + int dirty; /* sync needed */ + int modified; /* write_block was called */ - unsigned isize; /* size in blocks of superblock + I list */ - unsigned fsize; /* size in blocks of entire volume */ - unsigned swapsz; /* size in blocks of swap area */ - unsigned nfree; /* number of in core free blocks (0-100) */ - unsigned free [NICFREE]; /* in core free blocks */ - unsigned ninode; /* number of in core I nodes (0-100) */ - unsigned inode [NICINOD]; /* in core free I nodes */ - unsigned flock; /* lock during free list manipulation */ - unsigned ilock; /* lock during I list manipulation */ - unsigned fmod; /* super block modified flag */ - unsigned ronly; /* mounted read-only flag */ - long utime; /* current date of last update */ - unsigned tfree; /* total free blocks */ - unsigned tinode; /* total free inodes */ - char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ - unsigned lasti; /* start place for circular search */ - unsigned nbehind; /* est # free inodes before s_lasti */ - unsigned flags; /* mount time flags */ + unsigned isize; /* size in blocks of superblock + I list */ + unsigned fsize; /* size in blocks of entire volume */ + unsigned swapsz; /* size in blocks of swap area */ + unsigned nfree; /* number of in core free blocks (0-100) */ + unsigned free [NICFREE]; /* in core free blocks */ + unsigned ninode; /* number of in core I nodes (0-100) */ + unsigned inode [NICINOD]; /* in core free I nodes */ + unsigned flock; /* lock during free list manipulation */ + unsigned ilock; /* lock during I list manipulation */ + unsigned fmod; /* super block modified flag */ + unsigned ronly; /* mounted read-only flag */ + long utime; /* current date of last update */ + unsigned tfree; /* total free blocks */ + unsigned tinode; /* total free inodes */ + char fsmnt [MAXMNTLEN]; /* ordinary file mounted on */ + unsigned lasti; /* start place for circular search */ + unsigned nbehind; /* est # free inodes before s_lasti */ + unsigned flags; /* mount time flags */ } fs_t; typedef struct { - fs_t *fs; - unsigned number; - int dirty; /* save needed */ + fs_t *fs; + unsigned number; + int dirty; /* save needed */ - unsigned short mode; /* file type and access mode */ -#define INODE_MODE_FMT 0170000 /* type of file */ -#define INODE_MODE_FCHR 020000 /* character special */ -#define INODE_MODE_FDIR 040000 /* directory */ -#define INODE_MODE_FBLK 060000 /* block special */ -#define INODE_MODE_FREG 0100000 /* regular */ -#define INODE_MODE_FLNK 0120000 /* symbolic link */ -#define INODE_MODE_FSOCK 0140000 /* socket */ -#define INODE_MODE_SUID 04000 /* set user id on execution */ -#define INODE_MODE_SGID 02000 /* set group id on execution */ -#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ -#define INODE_MODE_READ 0400 /* read, write, execute permissions */ -#define INODE_MODE_WRITE 0200 -#define INODE_MODE_EXEC 0100 + unsigned short mode; /* file type and access mode */ +#define INODE_MODE_FMT 0170000 /* type of file */ +#define INODE_MODE_FCHR 020000 /* character special */ +#define INODE_MODE_FDIR 040000 /* directory */ +#define INODE_MODE_FBLK 060000 /* block special */ +#define INODE_MODE_FREG 0100000 /* regular */ +#define INODE_MODE_FLNK 0120000 /* symbolic link */ +#define INODE_MODE_FSOCK 0140000 /* socket */ +#define INODE_MODE_SUID 04000 /* set user id on execution */ +#define INODE_MODE_SGID 02000 /* set group id on execution */ +#define INODE_MODE_SVTX 01000 /* save swapped text even after use */ +#define INODE_MODE_READ 0400 /* read, write, execute permissions */ +#define INODE_MODE_WRITE 0200 +#define INODE_MODE_EXEC 0100 - unsigned short nlink; /* directory entries */ - unsigned uid; /* owner */ - unsigned gid; /* group */ - unsigned long size; /* size */ - unsigned addr [7]; /* device addresses constituting file */ - unsigned flags; /* user defined flags */ + unsigned short nlink; /* directory entries */ + unsigned uid; /* owner */ + unsigned gid; /* group */ + unsigned long size; /* size */ + unsigned addr [7]; /* device addresses constituting file */ + unsigned flags; /* user defined flags */ /* * Super-user and owner changeable flags. */ -#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ -#define USER_NODUMP 0x0001 /* do not dump file */ -#define USER_IMMUTABLE 0x0002 /* file may not be changed */ -#define USER_APPEND 0x0004 /* writes to file may only append */ +#define USER_SETTABLE 0x00ff /* mask of owner changeable flags */ +#define USER_NODUMP 0x0001 /* do not dump file */ +#define USER_IMMUTABLE 0x0002 /* file may not be changed */ +#define USER_APPEND 0x0004 /* writes to file may only append */ /* * Super-user changeable flags. */ -#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ -#define SYS_ARCHIVED 0x0100 /* file is archived */ -#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ -#define SYS_APPEND 0x0400 /* writes to file may only append */ +#define SYS_SETTABLE 0xff00 /* mask of superuser changeable flags */ +#define SYS_ARCHIVED 0x0100 /* file is archived */ +#define SYS_IMMUTABLE 0x0200 /* file may not be changed */ +#define SYS_APPEND 0x0400 /* writes to file may only append */ - long atime; /* time last accessed */ - long mtime; /* time last modified */ - long ctime; /* time created */ + long atime; /* time last accessed */ + long mtime; /* time last modified */ + long ctime; /* time created */ } fs_inode_t; typedef struct { - unsigned ino; - unsigned reclen; - unsigned namlen; - char name [63+1]; + unsigned ino; + unsigned reclen; + unsigned namlen; + char name [63+1]; } fs_dirent_t; typedef void (*fs_directory_scanner_t) (fs_inode_t *dir, - fs_inode_t *file, char *dirname, char *filename, void *arg); + fs_inode_t *file, char *dirname, char *filename, void *arg); typedef struct { - fs_inode_t inode; - int writable; /* write allowed */ - unsigned long offset; /* current i/o offset */ + fs_inode_t inode; + int writable; /* write allowed */ + unsigned long offset; /* current i/o offset */ } fs_file_t; typedef enum { - INODE_OP_LOOKUP, /* lookup inode by name */ - INODE_OP_CREATE, /* create new file */ - INODE_OP_DELETE, /* delete file */ - INODE_OP_LINK, /* make a link to a file */ + INODE_OP_LOOKUP, /* lookup inode by name */ + INODE_OP_CREATE, /* create new file */ + INODE_OP_DELETE, /* delete file */ + INODE_OP_LINK, /* make a link to a file */ } fs_op_t; int fs_seek (fs_t *fs, unsigned long offset); @@ -167,7 +167,7 @@ int fs_open (fs_t *fs, const char *filename, int writable); void fs_close (fs_t *fs); int fs_sync (fs_t *fs, int force); int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes); + unsigned swap_kbytes); int fs_check (fs_t *fs); void fs_print (fs_t *fs, FILE *out); @@ -179,12 +179,12 @@ void fs_inode_clear (fs_inode_t *inode); void fs_inode_truncate (fs_inode_t *inode, unsigned long size); void fs_inode_print (fs_inode_t *inode, FILE *out); int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes); + unsigned char *data, unsigned long bytes); int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - fs_op_t op, int mode); + fs_op_t op, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); @@ -196,14 +196,14 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk); void fs_directory_scan (fs_inode_t *inode, char *dirname, - fs_directory_scanner_t scanner, void *arg); + fs_directory_scanner_t scanner, void *arg); void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent); void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data); int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode); int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag); int fs_file_read (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_write (fs_file_t *file, unsigned char *data, - unsigned long bytes); + unsigned long bytes); int fs_file_close (fs_file_t *file); diff --git a/tools/fsutil/check.c b/tools/fsutil/check.c index 6240cde..2aa9e80 100644 --- a/tools/fsutil/check.c +++ b/tools/fsutil/check.c @@ -31,138 +31,138 @@ extern int verbose; -#define MAXDUP 10 /* limit on dup blks (per inode) */ -#define MAXBAD 10 /* limit on bad blks (per inode) */ -#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ -#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ +#define MAXDUP 10 /* limit on dup blks (per inode) */ +#define MAXBAD 10 /* limit on bad blks (per inode) */ +#define DUP_LIST_SIZE 100 /* num of dup blocks to remember */ +#define LINK_LIST_SIZE 20 /* num zero link cnts to remember */ -#define STATE_BITS 2 /* bits per inode state */ -#define STATE_MASK 3 /* mask for inode state */ -#define STATES_PER_BYTE 4 /* inode states per byte */ -#define USTATE 0 /* inode not allocated */ -#define FSTATE 1 /* inode is file */ -#define DSTATE 2 /* inode is directory */ -#define CLEAR 3 /* inode is to be cleared */ +#define STATE_BITS 2 /* bits per inode state */ +#define STATE_MASK 3 /* mask for inode state */ +#define STATES_PER_BYTE 4 /* inode states per byte */ +#define USTATE 0 /* inode not allocated */ +#define FSTATE 1 /* inode is file */ +#define DSTATE 2 /* inode is directory */ +#define CLEAR 3 /* inode is to be cleared */ -#define DATA 1 /* flags for scan_inode() */ -#define ADDR 0 +#define DATA 1 /* flags for scan_inode() */ +#define ADDR 0 -#define ALTERD 010 /* values returned by scan functions */ -#define KEEPON 004 -#define SKIP 002 -#define STOP 001 +#define ALTERD 010 /* values returned by scan functions */ +#define KEEPON 004 +#define SKIP 002 +#define STOP 001 -#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) +#define outrange(fs,x) ((x) < (fs)->isize || (x) >= (fs)->fsize) /* block scan function, called by scan_inode for every file block */ typedef int scanner_t (fs_inode_t *inode, unsigned blk, void *arg); -static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ -static unsigned buf_bno; /* buffer block number */ -static int buf_dirty; /* buffer data modified */ +static unsigned char buf_data [BSDFS_BSIZE]; /* buffer data for scan_directory */ +static unsigned buf_bno; /* buffer block number */ +static int buf_dirty; /* buffer data modified */ -static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ -static unsigned *dup_end; /* next entry in dup table */ -static unsigned *dup_multi; /* multiple dups part of table */ +static unsigned dup_list [DUP_LIST_SIZE]; /* dup block table */ +static unsigned *dup_end; /* next entry in dup table */ +static unsigned *dup_multi; /* multiple dups part of table */ -static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ -static unsigned *bad_link_end; /* next entry in table */ +static unsigned bad_link_list [LINK_LIST_SIZE]; /* inos with zero link cnts */ +static unsigned *bad_link_end; /* next entry in table */ -static char *block_map; /* primary blk allocation map */ -static char *free_map; /* secondary blk allocation map */ -static char *state_map; /* inode state table */ -static int *link_count; /* link count table */ +static char *block_map; /* primary blk allocation map */ +static char *free_map; /* secondary blk allocation map */ +static char *state_map; /* inode state table */ +static int *link_count; /* link count table */ -static char pathname [256]; /* file path name for pass2 */ -static char *pathp; /* pointer to pathname position */ -static char *thisname; /* ptr to current pathname component */ +static char pathname [256]; /* file path name for pass2 */ +static char *pathp; /* pointer to pathname position */ +static char *thisname; /* ptr to current pathname component */ -static char *lost_found_name = "lost+found"; -static unsigned lost_found_inode; /* lost & found directory */ +static char *lost_found_name = "lost+found"; +static unsigned lost_found_inode; /* lost & found directory */ -static int free_list_corrupted; /* corrupted free list */ -static int bad_blocks; /* num of bad blks seen (per inode) */ -static int dup_blocks; /* num of dup blks seen (per inode) */ +static int free_list_corrupted; /* corrupted free list */ +static int bad_blocks; /* num of bad blks seen (per inode) */ +static int dup_blocks; /* num of dup blks seen (per inode) */ -static char *find_inode_name; /* searching for this name */ -static unsigned find_inode_result; /* result of inode search */ -static unsigned lost_inode; /* lost file to reconnect */ +static char *find_inode_name; /* searching for this name */ +static unsigned find_inode_result; /* result of inode search */ +static unsigned lost_inode; /* lost file to reconnect */ -static unsigned long scan_filesize; /* file size, decremented during scan */ -static unsigned total_files; /* number of files seen */ +static unsigned long scan_filesize; /* file size, decremented during scan */ +static unsigned total_files; /* number of files seen */ static void set_inode_state (unsigned inum, int s) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - state_map [byte] &= ~(STATE_MASK << shift); - state_map [byte] |= s << shift; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + state_map [byte] &= ~(STATE_MASK << shift); + state_map [byte] |= s << shift; } static int inode_state (unsigned inum) { - unsigned int byte, shift; + unsigned int byte, shift; - byte = inum / STATES_PER_BYTE; - shift = inum % STATES_PER_BYTE * STATE_BITS; - return (state_map [byte] >> shift) & STATE_MASK; + byte = inum / STATES_PER_BYTE; + shift = inum % STATES_PER_BYTE * STATE_BITS; + return (state_map [byte] >> shift) & STATE_MASK; } static int block_is_busy (unsigned blk) { - return block_map [blk >> 3] & (1 << (blk & 7)); + return block_map [blk >> 3] & (1 << (blk & 7)); } static void mark_block_busy (unsigned blk) { - block_map [blk >> 3] |= 1 << (blk & 7); + block_map [blk >> 3] |= 1 << (blk & 7); } static void mark_block_free (unsigned blk) { - block_map [blk >> 3] &= ~(1 << (blk & 7)); + block_map [blk >> 3] &= ~(1 << (blk & 7)); } static void mark_free_list (unsigned blk) { - free_map [blk >> 3] |= 1 << (blk & 7); + free_map [blk >> 3] |= 1 << (blk & 7); } static int in_free_list (unsigned blk) { - return free_map [blk >> 3] & (1 << (blk & 7)); + return free_map [blk >> 3] & (1 << (blk & 7)); } static void print_io_error (char *s, unsigned blk) { - printf ("\nCAN NOT %s: BLK %d\n", s, blk); + printf ("\nCAN NOT %s: BLK %d\n", s, blk); } static void buf_flush (fs_t *fs) { - if (buf_dirty && fs->writable) { + if (buf_dirty && fs->writable) { /*printf ("WRITE blk %d\n", buf_bno);*/ - if (! fs_write_block (fs, buf_bno, buf_data)) - print_io_error ("WRITE", buf_bno); - } - buf_dirty = 0; + if (! fs_write_block (fs, buf_bno, buf_data)) + print_io_error ("WRITE", buf_bno); + } + buf_dirty = 0; } static int buf_get (fs_t *fs, unsigned blk) { - if (buf_bno == blk) - return 1; - buf_flush (fs); + if (buf_bno == blk) + return 1; + buf_flush (fs); /*printf ("read blk %d\n", blk);*/ - if (! fs_read_block (fs, blk, buf_data)) { - print_io_error ("READ", blk); - buf_bno = (unsigned)-1; - return 0; - } - buf_bno = blk; - return 1; + if (! fs_read_block (fs, blk, buf_data)) { + print_io_error ("READ", blk); + buf_bno = (unsigned)-1; + return 0; + } + buf_bno = blk; + return 1; } /* @@ -170,39 +170,39 @@ static int buf_get (fs_t *fs, unsigned blk) * and for every block call the given function. */ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, - int double_indirect, int flg, scanner_t *func, void *arg) + int double_indirect, int flg, scanner_t *func, void *arg) { - unsigned nb; - int ret, i; - unsigned char data [BSDFS_BSIZE]; + unsigned nb; + int ret, i; + unsigned char data [BSDFS_BSIZE]; /*printf ("check %siblock %d: \n", double_indirect > 1 ? "triple " : double_indirect ? "double " : "", blk);*/ - if (flg == ADDR) { - ret = (*func) (inode, blk, arg); - if (! (ret & KEEPON)) - return ret; - } - if (outrange (inode->fs, blk)) /* protect thyself */ - return SKIP; + if (flg == ADDR) { + ret = (*func) (inode, blk, arg); + if (! (ret & KEEPON)) + return ret; + } + if (outrange (inode->fs, blk)) /* protect thyself */ + return SKIP; - if (! fs_read_block (inode->fs, blk, data)) { - print_io_error ("READ", blk); - return SKIP; - } - for (i = 0; i < BSDFS_BSIZE; i+=2) { - nb = data [i+1] << 8 | data [i]; - if (nb) { - if (double_indirect) - ret = scan_indirect_block (inode, nb, - double_indirect - 1, flg, func, arg); - else - ret = (*func) (inode, nb, arg); + if (! fs_read_block (inode->fs, blk, data)) { + print_io_error ("READ", blk); + return SKIP; + } + for (i = 0; i < BSDFS_BSIZE; i+=2) { + nb = data [i+1] << 8 | data [i]; + if (nb) { + if (double_indirect) + ret = scan_indirect_block (inode, nb, + double_indirect - 1, flg, func, arg); + else + ret = (*func) (inode, nb, arg); - if (ret & STOP) - return ret; - } - } - return KEEPON; + if (ret & STOP) + return ret; + } + } + return KEEPON; } /* @@ -214,50 +214,50 @@ static int scan_indirect_block (fs_inode_t *inode, unsigned blk, */ static int scan_inode (fs_inode_t *inode, int flg, scanner_t *func, void *arg) { - unsigned *ap; - int ret; + unsigned *ap; + int ret; /*printf ("check inode %d: %#o\n", inode->number, inode->mode);*/ - if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || - ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) - return KEEPON; - scan_filesize = inode->size; + if (((inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) || + ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR)) + return KEEPON; + scan_filesize = inode->size; - /* Check direct blocks. */ - for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { - if (*ap) { - ret = (*func) (inode, *ap, arg); - if (ret & STOP) - return ret; - } - } - if (inode->addr[NADDR-3]) { - /* Check the indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-2]) { - /* Check the double indirect block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, - flg, func, arg); - if (ret & STOP) - return (ret); - } - if (inode->addr[NADDR-1]) { - /* Check the last (triple indirect) block. */ - ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, - flg, func, arg); - if (ret & STOP) - return (ret); - } - return KEEPON; + /* Check direct blocks. */ + for (ap = inode->addr; ap < &inode->addr[NDADDR]; ap++) { + if (*ap) { + ret = (*func) (inode, *ap, arg); + if (ret & STOP) + return ret; + } + } + if (inode->addr[NADDR-3]) { + /* Check the indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-3], 0, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-2]) { + /* Check the double indirect block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-2], 1, + flg, func, arg); + if (ret & STOP) + return (ret); + } + if (inode->addr[NADDR-1]) { + /* Check the last (triple indirect) block. */ + ret = scan_indirect_block (inode, inode->addr[NADDR-1], 2, + flg, func, arg); + if (ret & STOP) + return (ret); + } + return KEEPON; } static void print_block_error (char *s, unsigned blk, unsigned inum) { - printf ("%u %s I=%u\n", blk, s, inum); + printf ("%u %s I=%u\n", blk, s, inum); } /* @@ -267,64 +267,64 @@ static void print_block_error (char *s, unsigned blk, unsigned inum) */ static int pass1 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; /*printf ("pass1 inode %d block %d: \n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - print_block_error ("BAD", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); - return STOP; - } - return SKIP; - } - if (block_is_busy (blk)) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - if (++dup_blocks >= MAXDUP) { - printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); - return STOP; - } - if (dup_end >= &dup_list[DUP_LIST_SIZE]) { - printf ("DUP TABLE OVERFLOW.\n"); - return STOP; - } - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - *dup_end++ = blk; - break; - } - } - if (dlp >= dup_multi) { - *dup_end++ = *dup_multi; - *dup_multi++ = blk; - } - } else { - if (blocks) - ++*blocks; - mark_block_busy (blk); - } - return KEEPON; + if (outrange (inode->fs, blk)) { + print_block_error ("BAD", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS I=%u\n", inode->number); + return STOP; + } + return SKIP; + } + if (block_is_busy (blk)) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + if (++dup_blocks >= MAXDUP) { + printf ("EXCESSIVE DUP BLKS I=%u\n", inode->number); + return STOP; + } + if (dup_end >= &dup_list[DUP_LIST_SIZE]) { + printf ("DUP TABLE OVERFLOW.\n"); + return STOP; + } + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + *dup_end++ = blk; + break; + } + } + if (dlp >= dup_multi) { + *dup_end++ = *dup_multi; + *dup_multi++ = blk; + } + } else { + if (blocks) + ++*blocks; + mark_block_busy (blk); + } + return KEEPON; } static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; + unsigned *dlp; - if (outrange (inode->fs, blk)) - return SKIP; - for (dlp = dup_list; dlp < dup_multi; dlp++) { - if (*dlp == blk) { - print_block_error ("DUP", blk, inode->number); - set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ - *dlp = *--dup_multi; - *dup_multi = blk; - return (dup_multi == dup_list ? STOP : KEEPON); - } - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + for (dlp = dup_list; dlp < dup_multi; dlp++) { + if (*dlp == blk) { + print_block_error ("DUP", blk, inode->number); + set_inode_state (inode->number, CLEAR); /* mark for possible clearing */ + *dlp = *--dup_multi; + *dup_multi = blk; + return (dup_multi == dup_list ? STOP : KEEPON); + } + } + return KEEPON; } /* @@ -333,68 +333,68 @@ static int pass1b (fs_inode_t *inode, unsigned blk, void *arg) */ static int scan_directory (fs_inode_t *inode, unsigned blk, void *arg) { - fs_dirent_t direntry; - unsigned char *dirp; - int (*func) () = arg; - int n; + fs_dirent_t direntry; + unsigned char *dirp; + int (*func) () = arg; + int n; /*printf ("scan_directory: I=%d, blk=%d\n", inode->number, blk);*/ - if (outrange (inode->fs, blk)) { - scan_filesize -= BSDFS_BSIZE; - return SKIP; - } - dirp = buf_data; - while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { - if (! buf_get (inode->fs, blk)) { - scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); - return SKIP; - } - fs_dirent_unpack (&direntry, dirp); - if (direntry.reclen == 0) - break; + if (outrange (inode->fs, blk)) { + scan_filesize -= BSDFS_BSIZE; + return SKIP; + } + dirp = buf_data; + while (dirp < &buf_data[BSDFS_BSIZE] && scan_filesize > 0) { + if (! buf_get (inode->fs, blk)) { + scan_filesize -= (&buf_data[BSDFS_BSIZE] - dirp); + return SKIP; + } + fs_dirent_unpack (&direntry, dirp); + if (direntry.reclen == 0) + break; - /* For every directory entry, call handler. */ - n = (*func) (inode->fs, &direntry); + /* For every directory entry, call handler. */ + n = (*func) (inode->fs, &direntry); - if (n & ALTERD) { - if (buf_get (inode->fs, blk)) { - fs_dirent_pack (dirp, &direntry); - buf_dirty = 1; - } else - n &= ~ALTERD; - } - if (n & STOP) - return n; - dirp += direntry.reclen; - scan_filesize -= direntry.reclen; - } - return (scan_filesize > 0) ? KEEPON : STOP; + if (n & ALTERD) { + if (buf_get (inode->fs, blk)) { + fs_dirent_pack (dirp, &direntry); + buf_dirty = 1; + } else + n &= ~ALTERD; + } + if (n & STOP) + return n; + dirp += direntry.reclen; + scan_filesize -= direntry.reclen; + } + return (scan_filesize > 0) ? KEEPON : STOP; } static void print_inode (fs_inode_t *inode) { - char *p; + char *p; - printf (" I=%u ", inode->number); - printf (" OWNER=%d ", inode->uid); - printf ("MODE=%o\n", inode->mode); - printf ("SIZE=%ld ", inode->size); - p = ctime (&inode->mtime); - printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); + printf (" I=%u ", inode->number); + printf (" OWNER=%d ", inode->uid); + printf ("MODE=%o\n", inode->mode); + printf ("SIZE=%ld ", inode->size); + p = ctime (&inode->mtime); + printf ("MTIME=%12.12s %4.4s\n", p+4, p+20); } static void print_dir_error (fs_t *fs, unsigned inum, char *s) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) { - printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); - return; - } - printf ("%s ", s); - print_inode (&inode); - printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); + if (! fs_inode_get (fs, &inode, inum)) { + printf ("%s I=%u\nNAME=%s\n", s, inum, pathname); + return; + } + printf ("%s ", s); + print_inode (&inode); + printf ("%s=%s\n", ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE", pathname); } static void scan_pass2 (fs_t *fs, unsigned inum); @@ -405,53 +405,53 @@ static void scan_pass2 (fs_t *fs, unsigned inum); */ static int pass2 (fs_t *fs, fs_dirent_t *dirp) { - int inum, ret = KEEPON; - fs_inode_t inode; + int inum, ret = KEEPON; + fs_inode_t inode; - inum = dirp->ino; - if (inum == 0) - return KEEPON; + inum = dirp->ino; + if (inum == 0) + return KEEPON; - /* Copy file name from dirp to pathp */ - thisname = pathp; - strcpy (pathp, dirp->name); - pathp += strlen (pathp); + /* Copy file name from dirp to pathp */ + thisname = pathp; + strcpy (pathp, dirp->name); + pathp += strlen (pathp); /*printf ("%s %d\n", pathname, inum);*/ - if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || - inum < BSDFS_ROOT_INODE) - print_dir_error (fs, inum, "I OUT OF RANGE"); - else { -again: switch (inode_state (inum)) { - case USTATE: - print_dir_error (fs, inum, "UNALLOCATED"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - break; - case CLEAR: - print_dir_error (fs, inum, "DUP/BAD"); - if (fs->writable) { - dirp->ino = 0; - ret |= ALTERD; - break; - } - if (! fs_inode_get (fs, &inode, inum)) - break; - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - goto again; - case FSTATE: - --link_count [inum]; - break; - case DSTATE: - --link_count [inum]; - scan_pass2 (fs, inum); - } - } - pathp = thisname; - return ret; + if (inum > (fs->isize - 1) * BSDFS_INODES_PER_BLOCK || + inum < BSDFS_ROOT_INODE) + print_dir_error (fs, inum, "I OUT OF RANGE"); + else { +again: switch (inode_state (inum)) { + case USTATE: + print_dir_error (fs, inum, "UNALLOCATED"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + break; + case CLEAR: + print_dir_error (fs, inum, "DUP/BAD"); + if (fs->writable) { + dirp->ino = 0; + ret |= ALTERD; + break; + } + if (! fs_inode_get (fs, &inode, inum)) + break; + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + goto again; + case FSTATE: + --link_count [inum]; + break; + case DSTATE: + --link_count [inum]; + scan_pass2 (fs, inum); + } + } + pathp = thisname; + return ret; } /* @@ -460,20 +460,20 @@ again: switch (inode_state (inum)) { */ static void scan_pass2 (fs_t *fs, unsigned inum) { - fs_inode_t inode; - char *savname; - unsigned long savsize; + fs_inode_t inode; + char *savname; + unsigned long savsize; - set_inode_state (inum, FSTATE); - if (! fs_inode_get (fs, &inode, inum)) - return; - *pathp++ = '/'; - savname = thisname; - savsize = scan_filesize; - scan_inode (&inode, DATA, scan_directory, pass2); - scan_filesize = savsize; - thisname = savname; - *--pathp = 0; + set_inode_state (inum, FSTATE); + if (! fs_inode_get (fs, &inode, inum)) + return; + *pathp++ = '/'; + savname = thisname; + savsize = scan_filesize; + scan_inode (&inode, DATA, scan_directory, pass2); + scan_filesize = savsize; + thisname = savname; + *--pathp = 0; } /* @@ -483,15 +483,15 @@ static void scan_pass2 (fs_t *fs, unsigned inum) */ static int find_inode (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino == 0) - return KEEPON; - if (strcmp (find_inode_name, dirp->name) == 0) { - if (dirp->ino >= BSDFS_ROOT_INODE && - dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - find_inode_result = dirp->ino; - return STOP; - } - return KEEPON; + if (dirp->ino == 0) + return KEEPON; + if (strcmp (find_inode_name, dirp->name) == 0) { + if (dirp->ino >= BSDFS_ROOT_INODE && + dirp->ino < (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + find_inode_result = dirp->ino; + return STOP; + } + return KEEPON; } /* @@ -500,11 +500,11 @@ static int find_inode (fs_t *fs, fs_dirent_t *dirp) */ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->ino) - return KEEPON; - dirp->ino = lost_inode; - sprintf (dirp->name, "#%05d", dirp->ino); - return ALTERD | STOP; + if (dirp->ino) + return KEEPON; + dirp->ino = lost_inode; + sprintf (dirp->name, "#%05d", dirp->ino); + return ALTERD | STOP; } /* @@ -512,12 +512,12 @@ static int make_lost_entry (fs_t *fs, fs_dirent_t *dirp) */ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) { - if (dirp->name[0] == '.' && dirp->name[1] == '.' && - dirp->name[2] == 0) { - dirp->ino = lost_found_inode; - return ALTERD | STOP; - } - return KEEPON; + if (dirp->name[0] == '.' && dirp->name[1] == '.' && + dirp->name[2] == 0) { + dirp->ino = lost_found_inode; + return ALTERD | STOP; + } + return KEEPON; } /* @@ -526,15 +526,15 @@ static int dotdot_to_lost_found (fs_t *fs, fs_dirent_t *dirp) */ static unsigned find_lost_found (fs_t *fs) { - fs_inode_t root; + fs_inode_t root; - /* Find lost_found directory inode number. */ - if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) - return 0; - find_inode_name = lost_found_name; - find_inode_result = 0; - scan_inode (&root, DATA, scan_directory, find_inode); - return find_inode_result; + /* Find lost_found directory inode number. */ + if (! fs_inode_get (fs, &root, BSDFS_ROOT_INODE)) + return 0; + find_inode_name = lost_found_name; + find_inode_result = 0; + scan_inode (&root, DATA, scan_directory, find_inode); + return find_inode_result; } /* @@ -542,61 +542,61 @@ static unsigned find_lost_found (fs_t *fs) */ static int move_to_lost_found (fs_inode_t *inode) { - fs_inode_t lost_found; + fs_inode_t lost_found; - printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (inode); - if (! inode->fs->writable) - return 0; + printf ("UNREF %s ", ((inode->mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (inode); + if (! inode->fs->writable) + return 0; - /* Get lost+found inode. */ - if (lost_found_inode == 0) { - /* Find lost_found directory inode number. */ - lost_found_inode = find_lost_found (inode->fs); - if (! lost_found_inode) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - } - if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || - ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || - inode_state (lost_found_inode) != FSTATE) { - printf ("SORRY. NO lost+found DIRECTORY\n\n"); - return 0; - } - if (lost_found.size % BSDFS_BSIZE) { - lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / - BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } + /* Get lost+found inode. */ + if (lost_found_inode == 0) { + /* Find lost_found directory inode number. */ + lost_found_inode = find_lost_found (inode->fs); + if (! lost_found_inode) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + } + if (! fs_inode_get (inode->fs, &lost_found, lost_found_inode) || + ((lost_found.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) || + inode_state (lost_found_inode) != FSTATE) { + printf ("SORRY. NO lost+found DIRECTORY\n\n"); + return 0; + } + if (lost_found.size % BSDFS_BSIZE) { + lost_found.size = (lost_found.size + BSDFS_BSIZE - 1) / + BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } - /* Put a file to lost+found. */ - lost_inode = inode->number; - if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & - ALTERD) == 0) { - printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); - return 0; - } - --link_count [inode->number]; + /* Put a file to lost+found. */ + lost_inode = inode->number; + if ((scan_inode (&lost_found, DATA, scan_directory, make_lost_entry) & + ALTERD) == 0) { + printf ("SORRY. NO SPACE IN lost+found DIRECTORY\n\n"); + return 0; + } + --link_count [inode->number]; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* For ".." set inode number to lost_found_inode. */ - scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); - if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { - lost_found.nlink++; - ++link_count [lost_found.number]; - if (! fs_inode_save (&lost_found, 1)) { - printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); - return 0; - } - } - printf ("DIR I=%u CONNECTED.\n\n", inode->number); - } - return 1; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* For ".." set inode number to lost_found_inode. */ + scan_inode (inode, DATA, scan_directory, dotdot_to_lost_found); + if (fs_inode_get (inode->fs, &lost_found, lost_found_inode)) { + lost_found.nlink++; + ++link_count [lost_found.number]; + if (! fs_inode_save (&lost_found, 1)) { + printf ("SORRY. ERROR WRITING lost+found I-NODE\n\n"); + return 0; + } + } + printf ("DIR I=%u CONNECTED.\n\n", inode->number); + } + return 1; } /* @@ -604,23 +604,23 @@ static int move_to_lost_found (fs_inode_t *inode) */ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) { - unsigned *dlp; - unsigned *blocks = arg; + unsigned *dlp; + unsigned *blocks = arg; - if (outrange (inode->fs, blk)) - return SKIP; - if (block_is_busy (blk)) { - /* Free block. */ - for (dlp = dup_list; dlp < dup_end; dlp++) - if (*dlp == blk) { - *dlp = *--dup_end; - return KEEPON; - } - mark_block_free (blk); - if (blocks) - --*blocks; - } - return KEEPON; + if (outrange (inode->fs, blk)) + return SKIP; + if (block_is_busy (blk)) { + /* Free block. */ + for (dlp = dup_list; dlp < dup_end; dlp++) + if (*dlp == blk) { + *dlp = *--dup_end; + return KEEPON; + } + mark_block_free (blk); + if (blocks) + --*blocks; + } + return KEEPON; } /* @@ -628,21 +628,21 @@ static int pass4 (fs_inode_t *inode, unsigned blk, void *arg) */ static void clear_inode (fs_t *fs, unsigned inum, char *msg) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (msg) { - printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? "DIR" : "FILE"); - print_inode (&inode); - } - if (fs->writable) { - total_files--; - scan_inode (&inode, ADDR, pass4, 0); - fs_inode_clear (&inode); - fs_inode_save (&inode, 1); - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (msg) { + printf ("%s %s", msg, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? "DIR" : "FILE"); + print_inode (&inode); + } + if (fs->writable) { + total_files--; + scan_inode (&inode, ADDR, pass4, 0); + fs_inode_clear (&inode); + fs_inode_save (&inode, 1); + } } /* @@ -651,26 +651,26 @@ static void clear_inode (fs_t *fs, unsigned inum, char *msg) */ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) { - fs_inode_t inode; + fs_inode_t inode; - if (! fs_inode_get (fs, &inode, inum)) - return; - if (inode.nlink == lcnt) { - /* No links to file - move to lost+found. */ - if (! move_to_lost_found (&inode)) - clear_inode (fs, inum, 0); - } else { - printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : - (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? - "DIR" : "FILE")); - print_inode (&inode); - printf ("COUNT %d SHOULD BE %d\n", - inode.nlink, inode.nlink - lcnt); - if (fs->writable) { - inode.nlink -= lcnt; - fs_inode_save (&inode, 1); - } - } + if (! fs_inode_get (fs, &inode, inum)) + return; + if (inode.nlink == lcnt) { + /* No links to file - move to lost+found. */ + if (! move_to_lost_found (&inode)) + clear_inode (fs, inum, 0); + } else { + printf ("LINK COUNT %s", (lost_found_inode==inum) ? lost_found_name : + (((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) ? + "DIR" : "FILE")); + print_inode (&inode); + printf ("COUNT %d SHOULD BE %d\n", + inode.nlink, inode.nlink - lcnt); + if (fs->writable) { + inode.nlink -= lcnt; + fs_inode_save (&inode, 1); + } + } } /* @@ -679,25 +679,25 @@ static void adjust_link_count (fs_t *fs, unsigned inum, unsigned lcnt) */ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) { - if (outrange (fs, blk)) { - free_list_corrupted = 1; - if (++bad_blocks >= MAXBAD) { - printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); - return STOP; - } - return SKIP; - } - if (in_free_list (blk)) { - free_list_corrupted = 1; - if (++dup_blocks >= DUP_LIST_SIZE) { - printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); - return STOP; - } - } else { - ++*free_blocks; - mark_free_list (blk); - } - return KEEPON; + if (outrange (fs, blk)) { + free_list_corrupted = 1; + if (++bad_blocks >= MAXBAD) { + printf ("EXCESSIVE BAD BLKS IN FREE LIST.\n"); + return STOP; + } + return SKIP; + } + if (in_free_list (blk)) { + free_list_corrupted = 1; + if (++dup_blocks >= DUP_LIST_SIZE) { + printf ("EXCESSIVE DUP BLKS IN FREE LIST.\n"); + return STOP; + } + } else { + ++*free_blocks; + mark_free_list (blk); + } + return KEEPON; } /* @@ -706,40 +706,40 @@ static int pass5 (fs_t *fs, unsigned blk, unsigned *free_blocks) */ static unsigned check_free_list (fs_t *fs) { - unsigned *ap, *base; - unsigned free_blocks, nfree; - unsigned data [BSDFS_BSIZE / 4]; - unsigned list [NICFREE]; - int i; + unsigned *ap, *base; + unsigned free_blocks, nfree; + unsigned data [BSDFS_BSIZE / 4]; + unsigned list [NICFREE]; + int i; - if (fs->nfree == 0) - return 0; - free_blocks = 0; - nfree = fs->nfree; - base = fs->free; - for (;;) { - if (nfree <= 0 || nfree > NICFREE) { - printf ("BAD FREEBLK COUNT\n"); - free_list_corrupted = 1; - break; - } - ap = base + nfree; - while (--ap > base) { - if (pass5 (fs, *ap, &free_blocks) == STOP) - return free_blocks; - } - if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) - break; - if (! fs_read_block (fs, *ap, (unsigned char*) data)) { - print_io_error ("READ", *ap); - break; - } - nfree = data[0]; - for (i=0; infree == 0) + return 0; + free_blocks = 0; + nfree = fs->nfree; + base = fs->free; + for (;;) { + if (nfree <= 0 || nfree > NICFREE) { + printf ("BAD FREEBLK COUNT\n"); + free_list_corrupted = 1; + break; + } + ap = base + nfree; + while (--ap > base) { + if (pass5 (fs, *ap, &free_blocks) == STOP) + return free_blocks; + } + if (*ap == 0 || pass5 (fs, *ap, &free_blocks) != KEEPON) + break; + if (! fs_read_block (fs, *ap, (unsigned char*) data)) { + print_io_error ("READ", *ap); + break; + } + nfree = data[0]; + for (i=0; ininode; i++) { - inum = fs->inode[i]; - if (inode_state (inum) != USTATE) { - printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); - if (fs->writable) { - fs->ninode = i - 1; - while (i < NICINOD) - fs->inode [i++] = 0; - fs->dirty = 1; - } - return; - } - } + for (i=0; ininode; i++) { + inum = fs->inode[i]; + if (inode_state (inum) != USTATE) { + printf ("ALLOCATED INODE(S) IN IFREE LIST\n"); + if (fs->writable) { + fs->ninode = i - 1; + while (i < NICINOD) + fs->inode [i++] = 0; + fs->dirty = 1; + } + return; + } + } } /* @@ -770,26 +770,26 @@ static void check_free_inode_list (fs_t *fs) */ static unsigned make_free_list (fs_t *fs) { - unsigned free_blocks, n; + unsigned free_blocks, n; - fs->nfree = 0; - fs->flock = 0; - fs->fmod = 0; - fs->ilock = 0; - fs->ronly = 0; - fs->dirty = 1; - free_blocks = 0; + fs->nfree = 0; + fs->flock = 0; + fs->fmod = 0; + fs->ilock = 0; + fs->ronly = 0; + fs->dirty = 1; + free_blocks = 0; - /* Build a list of free blocks */ - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize; n--) { - if (block_is_busy (n)) - continue; - ++free_blocks; - if (! fs_block_free (fs, n)) - return 0; - } - return free_blocks; + /* Build a list of free blocks */ + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize; n--) { + if (block_is_busy (n)) + continue; + ++free_blocks; + if (! fs_block_free (fs, n)) + return 0; + } + return free_blocks; } /* @@ -799,220 +799,220 @@ static unsigned make_free_list (fs_t *fs) */ int fs_check (fs_t *fs) { - fs_inode_t inode; - int n; - unsigned inum; - unsigned block_map_size; /* number of free blocks */ - unsigned free_blocks; /* number of free blocks */ - unsigned used_blocks; /* number of blocks used */ - unsigned last_allocated_inode; /* hiwater mark of inodes */ + fs_inode_t inode; + int n; + unsigned inum; + unsigned block_map_size; /* number of free blocks */ + unsigned free_blocks; /* number of free blocks */ + unsigned used_blocks; /* number of blocks used */ + unsigned last_allocated_inode; /* hiwater mark of inodes */ - if (fs->isize >= fs->fsize) { - printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", - fs->fsize, fs->isize); - return 0; - } - free_list_corrupted = 0; - total_files = 0; - used_blocks = 0; - dup_multi = dup_end = &dup_list[0]; - bad_link_end = &bad_link_list[0]; - lost_found_inode = 0; - buf_dirty = 0; - buf_bno = (unsigned) -1; + if (fs->isize >= fs->fsize) { + printf ("Bad filesystem size: total %d blocks with %d inode blocks\n", + fs->fsize, fs->isize); + return 0; + } + free_list_corrupted = 0; + total_files = 0; + used_blocks = 0; + dup_multi = dup_end = &dup_list[0]; + bad_link_end = &bad_link_list[0]; + lost_found_inode = 0; + buf_dirty = 0; + buf_bno = (unsigned) -1; - /* Allocate memory. */ - block_map_size = (fs->fsize + 7) / 8; - block_map = calloc (block_map_size, sizeof (*block_map)); - state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + - STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); - link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, - sizeof (*link_count)); - if (! block_map || ! state_map || ! link_count) { - printf ("Cannot allocate memory\n"); -fatal: if (block_map) - free (block_map); - if (state_map) - free (state_map); - if (link_count) - free (link_count); - return 0; - } + /* Allocate memory. */ + block_map_size = (fs->fsize + 7) / 8; + block_map = calloc (block_map_size, sizeof (*block_map)); + state_map = calloc (((fs->isize-1) * BSDFS_INODES_PER_BLOCK + + STATES_PER_BYTE) / STATES_PER_BYTE, sizeof (*state_map)); + link_count = calloc ((fs->isize-1) * BSDFS_INODES_PER_BLOCK + 1, + sizeof (*link_count)); + if (! block_map || ! state_map || ! link_count) { + printf ("Cannot allocate memory\n"); +fatal: if (block_map) + free (block_map); + if (state_map) + free (state_map); + if (link_count) + free (link_count); + return 0; + } - printf ("** Phase 1 - Check Blocks and Sizes\n"); - last_allocated_inode = 0; - for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (inode.mode & INODE_MODE_FMT) { + printf ("** Phase 1 - Check Blocks and Sizes\n"); + last_allocated_inode = 0; + for (inum = 1; inum <= (fs->isize-1) * BSDFS_INODES_PER_BLOCK; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (inode.mode & INODE_MODE_FMT) { /*printf ("inode %d: %#o\n", inode.number, inode.mode);*/ - last_allocated_inode = inum; - total_files++; - link_count[inum] = inode.nlink; - if (link_count[inum] <= 0) { - if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) - *bad_link_end++ = inum; - else { - printf ("LINK COUNT TABLE OVERFLOW\n"); - } - } - set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == - INODE_MODE_FDIR) ? DSTATE : FSTATE); - bad_blocks = dup_blocks = 0; - scan_inode (&inode, ADDR, pass1, &used_blocks); - n = inode_state (inum); - if (n == DSTATE || n == FSTATE) { - if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - (inode.size % 4) != 0) { - printf ("DIRECTORY MISALIGNED I=%u\n\n", - inode.number); - } - } - } - else if (inode.mode != 0) { - printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); - if (fs->writable) - fs_inode_clear (&inode); - } - fs_inode_save (&inode, 0); - } - if (dup_end != &dup_list[0]) { - printf ("** Phase 1b - Rescan For More DUPS\n"); - for (inum = 1; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == USTATE) - continue; - if (! fs_inode_get (fs, &inode, inum)) - continue; - if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) - break; - } - } + last_allocated_inode = inum; + total_files++; + link_count[inum] = inode.nlink; + if (link_count[inum] <= 0) { + if (bad_link_end < &bad_link_list[LINK_LIST_SIZE]) + *bad_link_end++ = inum; + else { + printf ("LINK COUNT TABLE OVERFLOW\n"); + } + } + set_inode_state (inum, ((inode.mode & INODE_MODE_FMT) == + INODE_MODE_FDIR) ? DSTATE : FSTATE); + bad_blocks = dup_blocks = 0; + scan_inode (&inode, ADDR, pass1, &used_blocks); + n = inode_state (inum); + if (n == DSTATE || n == FSTATE) { + if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + (inode.size % 4) != 0) { + printf ("DIRECTORY MISALIGNED I=%u\n\n", + inode.number); + } + } + } + else if (inode.mode != 0) { + printf ("PARTIALLY ALLOCATED INODE I=%u\n", inum); + if (fs->writable) + fs_inode_clear (&inode); + } + fs_inode_save (&inode, 0); + } + if (dup_end != &dup_list[0]) { + printf ("** Phase 1b - Rescan For More DUPS\n"); + for (inum = 1; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == USTATE) + continue; + if (! fs_inode_get (fs, &inode, inum)) + continue; + if (scan_inode (&inode, ADDR, pass1b, 0) & STOP) + break; + } + } - printf ("** Phase 2 - Check Pathnames\n"); - thisname = pathp = pathname; - switch (inode_state (BSDFS_ROOT_INODE)) { - case USTATE: - printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); - goto fatal; - case FSTATE: - printf ("ROOT INODE NOT DIRECTORY\n"); - if (! fs->writable) - goto fatal; - if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) - goto fatal; - inode.mode &= ~INODE_MODE_FMT; - inode.mode |= INODE_MODE_FDIR; - fs_inode_save (&inode, 1); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - case DSTATE: - scan_pass2 (fs, BSDFS_ROOT_INODE); - break; - case CLEAR: - printf ("DUPS/BAD IN ROOT INODE\n"); - set_inode_state (BSDFS_ROOT_INODE, DSTATE); - scan_pass2 (fs, BSDFS_ROOT_INODE); - } + printf ("** Phase 2 - Check Pathnames\n"); + thisname = pathp = pathname; + switch (inode_state (BSDFS_ROOT_INODE)) { + case USTATE: + printf ("ROOT INODE UNALLOCATED. TERMINATING.\n"); + goto fatal; + case FSTATE: + printf ("ROOT INODE NOT DIRECTORY\n"); + if (! fs->writable) + goto fatal; + if (! fs_inode_get (fs, &inode, BSDFS_ROOT_INODE)) + goto fatal; + inode.mode &= ~INODE_MODE_FMT; + inode.mode |= INODE_MODE_FDIR; + fs_inode_save (&inode, 1); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + case DSTATE: + scan_pass2 (fs, BSDFS_ROOT_INODE); + break; + case CLEAR: + printf ("DUPS/BAD IN ROOT INODE\n"); + set_inode_state (BSDFS_ROOT_INODE, DSTATE); + scan_pass2 (fs, BSDFS_ROOT_INODE); + } - printf ("** Phase 3 - Check Connectivity\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - if (inode_state (inum) == DSTATE) { - unsigned ino; + printf ("** Phase 3 - Check Connectivity\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + if (inode_state (inum) == DSTATE) { + unsigned ino; - find_inode_name = ".."; - ino = inum; - do { - if (! fs_inode_get (fs, &inode, ino)) - break; - find_inode_result = 0; - scan_inode (&inode, DATA, scan_directory, find_inode); - if (find_inode_result == 0) { - /* Parent link lost. */ - if (move_to_lost_found (&inode)) { - thisname = pathp = pathname; - *pathp++ = '?'; - scan_pass2 (fs, ino); - } - break; - } - ino = find_inode_result; - } while (inode_state (ino) == DSTATE); - } - } + find_inode_name = ".."; + ino = inum; + do { + if (! fs_inode_get (fs, &inode, ino)) + break; + find_inode_result = 0; + scan_inode (&inode, DATA, scan_directory, find_inode); + if (find_inode_result == 0) { + /* Parent link lost. */ + if (move_to_lost_found (&inode)) { + thisname = pathp = pathname; + *pathp++ = '?'; + scan_pass2 (fs, ino); + } + break; + } + ino = find_inode_result; + } while (inode_state (ino) == DSTATE); + } + } - printf ("** Phase 4 - Check Reference Counts\n"); - for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { - switch (inode_state (inum)) { - case FSTATE: - n = link_count [inum]; - if (n) - adjust_link_count (fs, inum, n); - else { - unsigned *blp; + printf ("** Phase 4 - Check Reference Counts\n"); + for (inum = BSDFS_ROOT_INODE; inum <= last_allocated_inode; inum++) { + switch (inode_state (inum)) { + case FSTATE: + n = link_count [inum]; + if (n) + adjust_link_count (fs, inum, n); + else { + unsigned *blp; - for (blp = bad_link_list; blp < bad_link_end; blp++) - if (*blp == inum) { - clear_inode (fs, inum, "UNREF"); - break; - } - } - break; - case DSTATE: - clear_inode (fs, inum, "UNREF"); - break; - case CLEAR: - clear_inode (fs, inum, "BAD/DUP"); - } - } - buf_flush (fs); + for (blp = bad_link_list; blp < bad_link_end; blp++) + if (*blp == inum) { + clear_inode (fs, inum, "UNREF"); + break; + } + } + break; + case DSTATE: + clear_inode (fs, inum, "UNREF"); + break; + case CLEAR: + clear_inode (fs, inum, "BAD/DUP"); + } + } + buf_flush (fs); - printf ("** Phase 5 - Check Free List\n"); - free (link_count); - check_free_inode_list (fs); - free (state_map); - bad_blocks = dup_blocks = 0; - free_map = calloc (block_map_size, sizeof (*free_map)); - if (! free_map) { - printf ("NO MEMORY TO CHECK FREE LIST\n"); - free_list_corrupted = 1; - free_blocks = 0; - } else { - memcpy (free_map, block_map, block_map_size); - free_blocks = check_free_list (fs); - free (free_map); - } - if (bad_blocks) - printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); - if (dup_blocks) - printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); - if (free_list_corrupted == 0) { - if (used_blocks + free_blocks != fs->fsize - fs->isize) { - printf ("%d BLK(S) MISSING\n", fs->fsize - - fs->isize - used_blocks - free_blocks); - free_list_corrupted = 1; - } - } - if (free_list_corrupted) { - printf ("BAD FREE LIST\n"); - if (! fs->writable) - free_list_corrupted = 0; - } + printf ("** Phase 5 - Check Free List\n"); + free (link_count); + check_free_inode_list (fs); + free (state_map); + bad_blocks = dup_blocks = 0; + free_map = calloc (block_map_size, sizeof (*free_map)); + if (! free_map) { + printf ("NO MEMORY TO CHECK FREE LIST\n"); + free_list_corrupted = 1; + free_blocks = 0; + } else { + memcpy (free_map, block_map, block_map_size); + free_blocks = check_free_list (fs); + free (free_map); + } + if (bad_blocks) + printf ("%d BAD BLKS IN FREE LIST\n", bad_blocks); + if (dup_blocks) + printf ("%d DUP BLKS IN FREE LIST\n", dup_blocks); + if (free_list_corrupted == 0) { + if (used_blocks + free_blocks != fs->fsize - fs->isize) { + printf ("%d BLK(S) MISSING\n", fs->fsize - + fs->isize - used_blocks - free_blocks); + free_list_corrupted = 1; + } + } + if (free_list_corrupted) { + printf ("BAD FREE LIST\n"); + if (! fs->writable) + free_list_corrupted = 0; + } - if (free_list_corrupted) { - printf ("** Phase 6 - Salvage Free List\n"); - free_blocks = make_free_list (fs); - } + if (free_list_corrupted) { + printf ("** Phase 6 - Salvage Free List\n"); + free_blocks = make_free_list (fs); + } - printf ("%d files %d blocks %d free\n", - total_files, used_blocks, free_blocks); - if (fs->modified) { - time (&fs->utime); - fs->dirty = 1; - } - buf_flush (fs); - fs_sync (fs, 0); - if (fs->modified) - printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); + printf ("%d files %d blocks %d free\n", + total_files, used_blocks, free_blocks); + if (fs->modified) { + time (&fs->utime); + fs->dirty = 1; + } + buf_flush (fs); + fs_sync (fs, 0); + if (fs->modified) + printf ("\n***** FILE SYSTEM WAS MODIFIED *****\n"); - free (block_map); - return 1; + free (block_map); + return 1; } diff --git a/tools/fsutil/create.c b/tools/fsutil/create.c index 28e8b43..66ef485 100644 --- a/tools/fsutil/create.c +++ b/tools/fsutil/create.c @@ -33,368 +33,370 @@ extern int verbose; int inode_build_list (fs_t *fs) { - fs_inode_t inode; - unsigned int inum, total_inodes; + fs_inode_t inode; + unsigned int inum, total_inodes; - total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; - for (inum = 1; inum <= total_inodes; inum++) { - if (! fs_inode_get (fs, &inode, inum)) - return 0; - if (inode.mode == 0) { - fs->inode [fs->ninode++] = inum; - if (fs->ninode >= NICINOD) - break; - } - } - return 1; + total_inodes = (fs->isize - 1) * BSDFS_INODES_PER_BLOCK; + for (inum = 1; inum <= total_inodes; inum++) { + if (! fs_inode_get (fs, &inode, inum)) + return 0; + if (inode.mode == 0) { + fs->inode [fs->ninode++] = inum; + if (fs->ninode >= NICINOD) + break; + } + } + return 1; } static int create_inode1 (fs_t *fs) { - fs_inode_t inode; + fs_inode_t inode; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG; - inode.fs = fs; - inode.number = 1; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG; + inode.fs = fs; + inode.number = 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_root_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_ROOT_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_ROOT_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = 12; - buf[12+5] = 12 >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = 12; + buf[12+5] = 12 >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - buf[24+0] = BSDFS_LOSTFOUND_INODE; - buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; - buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; - buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; - buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); - buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; - buf[24+6] = 10; - buf[24+7] = 10 >> 8; - memcpy (&buf[24+8], "lost+found\0\0", 12); + buf[24+0] = BSDFS_LOSTFOUND_INODE; + buf[24+1] = BSDFS_LOSTFOUND_INODE >> 8; + buf[24+2] = BSDFS_LOSTFOUND_INODE >> 16; + buf[24+3] = BSDFS_LOSTFOUND_INODE >> 24; + buf[24+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12); + buf[24+5] = (BSDFS_BSIZE - 12 - 12) >> 8; + buf[24+6] = 10; + buf[24+7] = 10 >> 8; + memcpy (&buf[24+8], "lost+found\0\0", 12); - if (fs->swapsz != 0) { - buf[24+4] = 20; - buf[24+5] = 20 >> 8; - buf[44+0] = BSDFS_SWAP_INODE; - buf[44+1] = BSDFS_SWAP_INODE >> 8; - buf[44+2] = BSDFS_SWAP_INODE >> 16; - buf[44+3] = BSDFS_SWAP_INODE >> 24; - buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); - buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; - buf[44+6] = 4; - buf[44+7] = 4 >> 8; - memcpy (&buf[44+8], "swap\0\0\0\0", 8); - } - inode.nlink = 3; + if (fs->swapsz != 0) { + buf[24+4] = 20; + buf[24+5] = 20 >> 8; + buf[44+0] = BSDFS_SWAP_INODE; + buf[44+1] = BSDFS_SWAP_INODE >> 8; + buf[44+2] = BSDFS_SWAP_INODE >> 16; + buf[44+3] = BSDFS_SWAP_INODE >> 24; + buf[44+4] = (unsigned char) (BSDFS_BSIZE - 12 - 12 - 20); + buf[44+5] = (BSDFS_BSIZE - 12 - 12 - 20) >> 8; + buf[44+6] = 4; + buf[44+7] = 4 >> 8; + memcpy (&buf[44+8], "swap\0\0\0\0", 8); + } + inode.nlink = 3; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static int create_lost_found_directory (fs_t *fs) { - fs_inode_t inode; - unsigned char buf [BSDFS_BSIZE]; - unsigned int bno; + fs_inode_t inode; + unsigned char buf [BSDFS_BSIZE]; + unsigned int bno; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FDIR | 0777; - inode.fs = fs; - inode.number = BSDFS_LOSTFOUND_INODE; - inode.size = BSDFS_BSIZE; - inode.flags = 0; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FDIR | 0777; + inode.fs = fs; + inode.number = BSDFS_LOSTFOUND_INODE; + inode.size = BSDFS_BSIZE; + inode.flags = 0; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - /* directory - put in extra links */ - memset (buf, 0, sizeof(buf)); - buf[0] = inode.number; - buf[1] = inode.number >> 8; - buf[2] = inode.number >> 16; - buf[3] = inode.number >> 24; - buf[4] = 12; - buf[5] = 12 >> 8; - buf[6] = 1; - buf[7] = 1 >> 8; - buf[8] = '.'; - buf[9] = 0; - buf[10] = 0; - buf[11] = 0; + /* directory - put in extra links */ + memset (buf, 0, sizeof(buf)); + buf[0] = inode.number; + buf[1] = inode.number >> 8; + buf[2] = inode.number >> 16; + buf[3] = inode.number >> 24; + buf[4] = 12; + buf[5] = 12 >> 8; + buf[6] = 1; + buf[7] = 1 >> 8; + buf[8] = '.'; + buf[9] = 0; + buf[10] = 0; + buf[11] = 0; - buf[12+0] = BSDFS_ROOT_INODE; - buf[12+1] = BSDFS_ROOT_INODE >> 8; - buf[12+2] = BSDFS_ROOT_INODE >> 16; - buf[12+3] = BSDFS_ROOT_INODE >> 24; - buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); - buf[12+5] = (BSDFS_BSIZE - 12) >> 8; - buf[12+6] = 2; - buf[12+7] = 2 >> 8; - buf[12+8] = '.'; - buf[12+9] = '.'; - buf[12+10] = 0; - buf[12+11] = 0; + buf[12+0] = BSDFS_ROOT_INODE; + buf[12+1] = BSDFS_ROOT_INODE >> 8; + buf[12+2] = BSDFS_ROOT_INODE >> 16; + buf[12+3] = BSDFS_ROOT_INODE >> 24; + buf[12+4] = (unsigned char) (BSDFS_BSIZE - 12); + buf[12+5] = (BSDFS_BSIZE - 12) >> 8; + buf[12+6] = 2; + buf[12+7] = 2 >> 8; + buf[12+8] = '.'; + buf[12+9] = '.'; + buf[12+10] = 0; + buf[12+11] = 0; - inode.nlink = 2; + inode.nlink = 2; - if (! fs_block_alloc (fs, &bno)) - return 0; - if (! fs_write_block (fs, bno, buf)) - return 0; - inode.addr[0] = bno; + if (! fs_block_alloc (fs, &bno)) + return 0; + if (! fs_write_block (fs, bno, buf)) + return 0; + inode.addr[0] = bno; - if (! fs_inode_save (&inode, 1)) - return 0; - fs->tinode--; - return 1; + if (! fs_inode_save (&inode, 1)) + return 0; + fs->tinode--; + return 1; } static void map_block_swap (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int bn, indir, newb, shift, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int bn, indir, newb, shift, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - inode->addr[lbn] = inode->fs->isize + lbn; - return; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + inode->addr[lbn] = inode->fs->isize + lbn; + return; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - shift = 0; - i = 1; - bn = lbn - (NADDR-3); - for (j=3; ; j--) { - if (j == 0) { - fprintf (stderr, "swap: too large size\n"); - exit (-1); - } - shift += NSHIFT; - i <<= NSHIFT; - if (bn < i) - break; - bn -= i; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + shift = 0; + i = 1; + bn = lbn - (NADDR-3); + for (j=3; ; j--) { + if (j == 0) { + fprintf (stderr, "swap: too large size\n"); + exit (-1); + } + shift += NSHIFT; + i <<= NSHIFT; + if (bn < i) + break; + bn -= i; + } - /* - * Fetch the first indirect block. - */ - indir = inode->addr [NADDR-j]; - if (indir == 0) { - if (! fs_block_alloc (inode->fs, &indir)) { -alloc_error: fprintf (stderr, "swap: cannot allocate indirect block\n"); - exit (-1); - } - if (verbose) - printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { -write_error: fprintf (stderr, "swap: cannot write indirect block %d\n", indir); - exit (-1); - } - inode->addr [NADDR-j] = indir; - } + /* + * Fetch the first indirect block. + */ + indir = inode->addr [NADDR-j]; + if (indir == 0) { + if (! fs_block_alloc (inode->fs, &indir)) { +alloc_error: + fprintf (stderr, "swap: cannot allocate indirect block\n"); + exit (-1); + } + if (verbose) + printf ("swap: allocate indirect block %d (j=%d)\n", indir, j); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) { +write_error: + fprintf (stderr, "swap: cannot write indirect block %d\n", indir); + exit (-1); + } + inode->addr [NADDR-j] = indir; + } - /* - * Fetch through the indirect blocks - */ - for (; ; j++) { - if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot read indirect block %d\n", indir); - exit (-1); - } - shift -= NSHIFT; - i = (bn >> shift) & NMASK; - if (j == 3) { - block[i] = inode->fs->isize + lbn; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - return; - } - if (block[i] != 0) { - indir = block [i]; - continue; - } - /* Allocate new indirect block. */ - if (! fs_block_alloc (inode->fs, &newb)) - goto alloc_error; - if (verbose) - printf ("swap: allocate new block %d (j=%d)\n", newb, j); - block[i] = newb; - if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) - goto write_error; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { - fprintf (stderr, "swap: cannot write block %d\n", newb); - exit (-1); - } - indir = newb; - } + /* + * Fetch through the indirect blocks + */ + for (; ; j++) { + if (! fs_read_block (inode->fs, indir, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot read indirect block %d\n", indir); + exit (-1); + } + shift -= NSHIFT; + i = (bn >> shift) & NMASK; + if (j == 3) { + block[i] = inode->fs->isize + lbn; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + return; + } + if (block[i] != 0) { + indir = block [i]; + continue; + } + /* Allocate new indirect block. */ + if (! fs_block_alloc (inode->fs, &newb)) + goto alloc_error; + if (verbose) + printf ("swap: allocate new block %d (j=%d)\n", newb, j); + block[i] = newb; + if (! fs_write_block (inode->fs, indir, (unsigned char*) block)) + goto write_error; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) { + fprintf (stderr, "swap: cannot write block %d\n", newb); + exit (-1); + } + indir = newb; + } } static int create_swap_file (fs_t *fs) { - fs_inode_t inode; - unsigned lbn; + fs_inode_t inode; + unsigned lbn; - memset (&inode, 0, sizeof(inode)); - inode.mode = INODE_MODE_FREG | 0400; - inode.fs = fs; - inode.number = BSDFS_SWAP_INODE; - inode.size = fs->swapsz * BSDFS_BSIZE; - inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; - inode.nlink = 1; - inode.dirty = 1; + memset (&inode, 0, sizeof(inode)); + inode.mode = INODE_MODE_FREG | 0400; + inode.fs = fs; + inode.number = BSDFS_SWAP_INODE; + inode.size = fs->swapsz * BSDFS_BSIZE; + inode.flags = /*SYS_IMMUTABLE |*/ USER_IMMUTABLE | USER_NODUMP; + inode.nlink = 1; + inode.dirty = 1; - time (&inode.ctime); - time (&inode.atime); - time (&inode.mtime); + time (&inode.ctime); + time (&inode.atime); + time (&inode.mtime); - for (lbn=0; lbnswapsz; lbn++) - map_block_swap (&inode, lbn); + for (lbn=0; lbnswapsz; lbn++) + map_block_swap (&inode, lbn); - if (! fs_inode_save (&inode, 0)) { - fprintf (stderr, "swap: cannot save file inode\n"); - return 0; - } - return 1; + if (! fs_inode_save (&inode, 0)) { + fprintf (stderr, "swap: cannot save file inode\n"); + return 0; + } + return 1; } int fs_create (fs_t *fs, const char *filename, unsigned kbytes, - unsigned swap_kbytes) + unsigned swap_kbytes) { - int n; - unsigned char buf [BSDFS_BSIZE]; - off_t bytes, offset; + int n; + unsigned char buf [BSDFS_BSIZE]; + off_t bytes, offset; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); - if (fs->fd < 0) - return 0; - fs->writable = 1; + fs->fd = open (fs->filename, O_CREAT | O_RDWR, 0666); + if (fs->fd < 0) + return 0; + fs->writable = 1; - /* get total disk size - * and inode block size */ - bytes = (off_t) kbytes * 1024ULL; - fs->fsize = bytes / BSDFS_BSIZE; - fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / - BSDFS_INODES_PER_BLOCK; - if (fs->isize < 2) - return 0; + /* get total disk size + * and inode block size */ + bytes = (off_t) kbytes * 1024ULL; + fs->fsize = bytes / BSDFS_BSIZE; + fs->isize = 1 + (fs->fsize / 16 + BSDFS_INODES_PER_BLOCK - 1) / + BSDFS_INODES_PER_BLOCK; + if (fs->isize < 2) + return 0; - /* make sure the file is of proper size */ - offset = lseek (fs->fd, bytes-1, SEEK_SET); - if (offset != bytes-1) - return 0; - if (write (fs->fd, "", 1) != 1) { - perror ("write"); - return 0; - } - lseek (fs->fd, 0, SEEK_SET); + /* make sure the file is of proper size */ + offset = lseek (fs->fd, bytes-1, SEEK_SET); + if (offset != bytes-1) + return 0; + if (write (fs->fd, "", 1) != 1) { + perror ("write"); + return 0; + } + lseek (fs->fd, 0, SEEK_SET); - /* build a list of free blocks */ - fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; - fs_block_free (fs, 0); - for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) - if (! fs_block_free (fs, n)) - return 0; + /* build a list of free blocks */ + fs->swapsz = swap_kbytes * 1024 / BSDFS_BSIZE; + fs_block_free (fs, 0); + for (n = fs->fsize - 1; n >= fs->isize + fs->swapsz; n--) + if (! fs_block_free (fs, n)) + return 0; - /* initialize inodes */ - memset (buf, 0, BSDFS_BSIZE); - if (! fs_seek (fs, BSDFS_BSIZE)) - return 0; - for (n=1; n < fs->isize; n++) { - if (! fs_write (fs, buf, BSDFS_BSIZE)) - return 0; - fs->tinode += BSDFS_INODES_PER_BLOCK; - } + /* initialize inodes */ + memset (buf, 0, BSDFS_BSIZE); + if (! fs_seek (fs, BSDFS_BSIZE)) + return 0; + for (n=1; n < fs->isize; n++) { + if (! fs_write (fs, buf, BSDFS_BSIZE)) + return 0; + fs->tinode += BSDFS_INODES_PER_BLOCK; + } - /* legacy empty inode 1 */ - if (! create_inode1 (fs)) - return 0; + /* legacy empty inode 1 */ + if (! create_inode1 (fs)) + return 0; - /* lost+found directory */ - if (! create_lost_found_directory (fs)) - return 0; + /* lost+found directory */ + if (! create_lost_found_directory (fs)) + return 0; - /* root directory */ - if (! create_root_directory (fs)) - return 0; + /* root directory */ + if (! create_root_directory (fs)) + return 0; - /* swap file */ - if (fs->swapsz != 0 && ! create_swap_file (fs)) - return 0; + /* swap file */ + if (fs->swapsz != 0 && ! create_swap_file (fs)) + return 0; - /* build a list of free inodes */ - if (! inode_build_list (fs)) - return 0; + /* build a list of free inodes */ + if (! inode_build_list (fs)) + return 0; - /* write out super block */ - return fs_sync (fs, 1); + /* write out super block */ + return fs_sync (fs, 1); } diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 8218edb..13d650c 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -29,68 +29,68 @@ extern int verbose; int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - fs_inode_truncate (&file->inode, 0); - fs_inode_save (&file->inode, 0); - file->writable = 1; - file->offset = 0; - return 1; + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if ((file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + fs_inode_truncate (&file->inode, 0); + fs_inode_save (&file->inode, 0); + file->writable = 1; + file->offset = 0; + return 1; } int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { - fprintf (stderr, "%s: inode open failed\n", name); - return 0; - } - if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Cannot open directory on write. */ - return 0; - } - file->writable = wflag; - file->offset = 0; - return 1; + if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { + fprintf (stderr, "%s: inode open failed\n", name); + return 0; + } + if (wflag && (file->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Cannot open directory on write. */ + return 0; + } + file->writable = wflag; + file->offset = 0; + return 1; } int fs_file_read (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", - file->inode.number, bytes, file->offset); - return 0; - } - file->offset += bytes; - return 1; + if (! fs_inode_read (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file read failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_write (fs_file_t *file, unsigned char *data, unsigned long bytes) { - if (! file->writable) - return 0; - if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { - fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", - file->inode.number, bytes, file->offset); - return 0; - } - file->offset += bytes; - return 1; + if (! file->writable) + return 0; + if (! fs_inode_write (&file->inode, file->offset, data, bytes)) { + fprintf (stderr, "inode %d: file write failed, %lu bytes at offset %lu\n", + file->inode.number, bytes, file->offset); + return 0; + } + file->offset += bytes; + return 1; } int fs_file_close (fs_file_t *file) { - if (file->writable) { - if (! fs_inode_save (&file->inode, 0)) { - fprintf (stderr, "inode %d: file close failed\n", - file->inode.number); - return 0; - } - } - return 1; + if (file->writable) { + if (! fs_inode_save (&file->inode, 0)) { + fprintf (stderr, "inode %d: file close failed\n", + file->inode.number); + return 0; + } + } + return 1; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 7fdfb8c..627b366 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -43,249 +43,249 @@ unsigned kbytes; unsigned swap_kbytes; static const char *program_version = - "BSD 2.x file system utility, version 1.1\n" - "Copyright (C) 2011-2014 Serge Vakulenko"; + "BSD 2.x file system utility, version 1.1\n" + "Copyright (C) 2011-2014 Serge Vakulenko"; static const char *program_bug_address = ""; static struct option program_options[] = { - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'V' }, - { "verbose", no_argument, 0, 'v' }, - { "add", no_argument, 0, 'a' }, - { "extract", no_argument, 0, 'x' }, - { "check", no_argument, 0, 'c' }, - { "fix", no_argument, 0, 'f' }, - { "mount", no_argument, 0, 'm' }, - { "new", required_argument, 0, 'n' }, - { "swap", required_argument, 0, 's' }, - { "manifest", required_argument, 0, 'M' }, - { 0 } + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { "verbose", no_argument, 0, 'v' }, + { "add", no_argument, 0, 'a' }, + { "extract", no_argument, 0, 'x' }, + { "check", no_argument, 0, 'c' }, + { "fix", no_argument, 0, 'f' }, + { "mount", no_argument, 0, 'm' }, + { "new", required_argument, 0, 'n' }, + { "swap", required_argument, 0, 's' }, + { "manifest", required_argument, 0, 'M' }, + { 0 } }; static void print_help (char *progname) { - char *p = strrchr (progname, '/'); - if (p) - progname = p+1; + char *p = strrchr (progname, '/'); + if (p) + progname = p+1; - printf ("%s\n", program_version); - printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" - "see the GNU General Public License for more details.\n"); - printf ("\n"); - printf ("Usage:\n"); - printf (" %s [--verbose] filesys.img\n", progname); - printf (" %s --add filesys.img files...\n", progname); - printf (" %s --extract filesys.img\n", progname); - printf (" %s --check [--fix] filesys.img\n", progname); - printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); - printf (" %s --mount filesys.img dir\n", progname); - printf ("\n"); - printf ("Options:\n"); - printf (" -a, --add Add files to filesystem.\n"); - printf (" -x, --extract Extract all files.\n"); - printf (" -c, --check Check filesystem, use -c -f to fix.\n"); - printf (" -f, --fix Fix bugs in filesystem.\n"); - printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); - printf (" Add files from specified directory (optional)\n"); - printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); - printf (" -M file, --manifest=file List of files and attributes to create.\n"); - printf (" -m, --mount Mount the filesystem.\n"); - printf (" -v, --verbose Be verbose.\n"); - printf (" -V, --version Print version information and then exit.\n"); - printf (" -h, --help Print this message.\n"); - printf ("\n"); - printf ("Report bugs to \"%s\".\n", program_bug_address); + printf ("%s\n", program_version); + printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" + "see the GNU General Public License for more details.\n"); + printf ("\n"); + printf ("Usage:\n"); + printf (" %s [--verbose] filesys.img\n", progname); + printf (" %s --add filesys.img files...\n", progname); + printf (" %s --extract filesys.img\n", progname); + printf (" %s --check [--fix] filesys.img\n", progname); + printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); + printf (" %s --mount filesys.img dir\n", progname); + printf ("\n"); + printf ("Options:\n"); + printf (" -a, --add Add files to filesystem.\n"); + printf (" -x, --extract Extract all files.\n"); + printf (" -c, --check Check filesystem, use -c -f to fix.\n"); + printf (" -f, --fix Fix bugs in filesystem.\n"); + printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); + printf (" Add files from specified directory (optional)\n"); + printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); + printf (" -M file, --manifest=file List of files and attributes to create.\n"); + printf (" -m, --mount Mount the filesystem.\n"); + printf (" -v, --verbose Be verbose.\n"); + printf (" -V, --version Print version information and then exit.\n"); + printf (" -h, --help Print this message.\n"); + printf ("\n"); + printf ("Report bugs to \"%s\".\n", program_bug_address); } void print_inode (fs_inode_t *inode, - char *dirname, char *filename, FILE *out) + char *dirname, char *filename, FILE *out) { - fprintf (out, "%s/%s", dirname, filename); - switch (inode->mode & INODE_MODE_FMT) { - case INODE_MODE_FDIR: - if (filename[0] != 0) - fprintf (out, "/"); - break; - case INODE_MODE_FCHR: - fprintf (out, " - char %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - case INODE_MODE_FBLK: - fprintf (out, " - block %d %d", - inode->addr[1] >> 8, inode->addr[1] & 0xff); - break; - default: - fprintf (out, " - %lu bytes", inode->size); - break; - } - fprintf (out, "\n"); + fprintf (out, "%s/%s", dirname, filename); + switch (inode->mode & INODE_MODE_FMT) { + case INODE_MODE_FDIR: + if (filename[0] != 0) + fprintf (out, "/"); + break; + case INODE_MODE_FCHR: + fprintf (out, " - char %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + case INODE_MODE_FBLK: + fprintf (out, " - block %d %d", + inode->addr[1] >> 8, inode->addr[1] & 0xff); + break; + default: + fprintf (out, " - %lu bytes", inode->size); + break; + } + fprintf (out, "\n"); } void print_indirect_block (fs_t *fs, unsigned int bno, FILE *out) { - unsigned short nb; - unsigned char data [BSDFS_BSIZE]; - int i; + unsigned short nb; + unsigned char data [BSDFS_BSIZE]; + int i; - fprintf (out, " [%d]", bno); - if (! fs_read_block (fs, bno, data)) { - fprintf (stderr, "read error at block %d\n", bno); - return; - } - for (i=0; imode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; - fprintf (out, " "); - for (i=0; iaddr[i] == 0) - continue; - fprintf (out, " %d", inode->addr[i]); - } - if (inode->addr[NDADDR] != 0) - print_indirect_block (inode->fs, inode->addr[NDADDR], out); - if (inode->addr[NDADDR+1] != 0) - print_double_indirect_block (inode->fs, - inode->addr[NDADDR+1], out); - if (inode->addr[NDADDR+2] != 0) - print_triple_indirect_block (inode->fs, - inode->addr[NDADDR+2], out); - fprintf (out, "\n"); + fprintf (out, " "); + for (i=0; iaddr[i] == 0) + continue; + fprintf (out, " %d", inode->addr[i]); + } + if (inode->addr[NDADDR] != 0) + print_indirect_block (inode->fs, inode->addr[NDADDR], out); + if (inode->addr[NDADDR+1] != 0) + print_double_indirect_block (inode->fs, + inode->addr[NDADDR+1], out); + if (inode->addr[NDADDR+2] != 0) + print_triple_indirect_block (inode->fs, + inode->addr[NDADDR+2], out); + fprintf (out, "\n"); } void extract_inode (fs_inode_t *inode, char *path) { - int fd, n, mode; - unsigned long offset; - unsigned char data [BSDFS_BSIZE]; + int fd, n, mode; + unsigned long offset; + unsigned char data [BSDFS_BSIZE]; - /* Allow read/write for user. */ - mode = (inode->mode & 0777) | 0600; - fd = open (path, O_CREAT | O_RDWR, mode); - if (fd < 0) { - perror (path); - return; - } - for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { - n = inode->size - offset; - if (n > BSDFS_BSIZE) - n = BSDFS_BSIZE; - if (! fs_inode_read (inode, offset, data, n)) { - fprintf (stderr, "%s: read error at offset %ld\n", - path, offset); - break; - } - if (write (fd, data, n) != n) { - fprintf (stderr, "%s: write error\n", path); - break; - } - } - close (fd); + /* Allow read/write for user. */ + mode = (inode->mode & 0777) | 0600; + fd = open (path, O_CREAT | O_RDWR, mode); + if (fd < 0) { + perror (path); + return; + } + for (offset = 0; offset < inode->size; offset += BSDFS_BSIZE) { + n = inode->size - offset; + if (n > BSDFS_BSIZE) + n = BSDFS_BSIZE; + if (! fs_inode_read (inode, offset, data, n)) { + fprintf (stderr, "%s: read error at offset %ld\n", + path, offset); + break; + } + if (write (fd, data, n) != n) { + fprintf (stderr, "%s: write error\n", path); + break; + } + } + close (fd); } void extractor (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path, *relpath; + FILE *out = arg; + char *path, *relpath; - if (verbose) - print_inode (inode, dirname, filename, out); + if (verbose) + print_inode (inode, dirname, filename, out); - if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && - (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) - return; + if ((inode->mode & INODE_MODE_FMT) != INODE_MODE_FDIR && + (inode->mode & INODE_MODE_FMT) != INODE_MODE_FREG) + return; - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - for (relpath=path; *relpath == '/'; relpath++) - continue; + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + for (relpath=path; *relpath == '/'; relpath++) + continue; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - if (mkdir (relpath, 0775) < 0 && errno != EEXIST) - perror (relpath); - /* Scan subdirectory. */ - fs_directory_scan (inode, path, extractor, arg); - } else { - extract_inode (inode, relpath); - } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + if (mkdir (relpath, 0775) < 0 && errno != EEXIST) + perror (relpath); + /* Scan subdirectory. */ + fs_directory_scan (inode, path, extractor, arg); + } else { + extract_inode (inode, relpath); + } } void scanner (fs_inode_t *dir, fs_inode_t *inode, - char *dirname, char *filename, void *arg) + char *dirname, char *filename, void *arg) { - FILE *out = arg; - char *path; + FILE *out = arg; + char *path; - print_inode (inode, dirname, filename, out); + print_inode (inode, dirname, filename, out); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (inode, out); - if (verbose > 2) { - fs_inode_print (inode, out); - printf ("--------\n"); - } - } - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && - inode->number != BSDFS_ROOT_INODE) { - /* Scan subdirectory. */ - path = alloca (strlen (dirname) + strlen (filename) + 2); - strcpy (path, dirname); - strcat (path, "/"); - strcat (path, filename); - fs_directory_scan (inode, path, scanner, arg); - } + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (inode, out); + if (verbose > 2) { + fs_inode_print (inode, out); + printf ("--------\n"); + } + } + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR && + inode->number != BSDFS_ROOT_INODE) { + /* Scan subdirectory. */ + path = alloca (strlen (dirname) + strlen (filename) + 2); + strcpy (path, dirname); + strcat (path, "/"); + strcat (path, filename); + fs_directory_scan (inode, path, scanner, arg); + } } /* @@ -293,46 +293,46 @@ void scanner (fs_inode_t *dir, fs_inode_t *inode, */ void add_directory (fs_t *fs, char *name) { - fs_inode_t dir, parent; - char buf [BSDFS_BSIZE], *p; + fs_inode_t dir, parent; + char buf [BSDFS_BSIZE], *p; - /* Open parent directory. */ - strcpy (buf, name); - p = strrchr (buf, '/'); - if (p) - *p = 0; - else - *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { - fprintf (stderr, "%s: cannot open directory\n", buf); - return; - } + /* Open parent directory. */ + strcpy (buf, name); + p = strrchr (buf, '/'); + if (p) + *p = 0; + else + *buf = 0; + if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { + fprintf (stderr, "%s: cannot open directory\n", buf); + return; + } - /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); - if (! done) { - fprintf (stderr, "%s: directory inode create failed\n", name); - return; - } - if (done == 1) { - /* The directory already existed. */ - return; - } - fs_inode_save (&dir, 0); + /* Create directory. */ + int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); + if (! done) { + fprintf (stderr, "%s: directory inode create failed\n", name); + return; + } + if (done == 1) { + /* The directory already existed. */ + return; + } + fs_inode_save (&dir, 0); - /* Make parent link '..' */ - strcpy (buf, name); - strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { - fprintf (stderr, "%s: dotdot link failed\n", name); - return; - } - if (! fs_inode_get (fs, &parent, parent.number)) { - fprintf (stderr, "inode %d: cannot open parent\n", parent.number); - return; - } - ++parent.nlink; - fs_inode_save (&parent, 1); + /* Make parent link '..' */ + strcpy (buf, name); + strcat (buf, "/.."); + if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { + fprintf (stderr, "%s: dotdot link failed\n", name); + return; + } + if (! fs_inode_get (fs, &parent, parent.number)) { + fprintf (stderr, "inode %d: cannot open parent\n", parent.number); + return; + } + ++parent.nlink; + fs_inode_save (&parent, 1); /*printf ("*** inode %d: increment link counter to %d\n", parent.number, parent.nlink);*/ } @@ -341,25 +341,25 @@ void add_directory (fs_t *fs, char *name) */ void add_device (fs_t *fs, char *name, char *spec) { - fs_inode_t dev; - int majr, minr; - char type; + fs_inode_t dev; + int majr, minr; + char type; - if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || - (type != 'c' && type != 'b') || - majr < 0 || majr > 255 || minr < 0 || minr > 255) { - fprintf (stderr, "%s: invalid device specification\n", spec); - fprintf (stderr, "expected c: or b:\n"); - return; - } - if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | - ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { - fprintf (stderr, "%s: device inode create failed\n", name); - return; - } - dev.addr[1] = majr << 8 | minr; - time (&dev.mtime); - fs_inode_save (&dev, 1); + if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || + (type != 'c' && type != 'b') || + majr < 0 || majr > 255 || minr < 0 || minr > 255) { + fprintf (stderr, "%s: invalid device specification\n", spec); + fprintf (stderr, "expected c: or b:\n"); + return; + } + if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | + ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { + fprintf (stderr, "%s: device inode create failed\n", name); + return; + } + dev.addr[1] = majr << 8 | minr; + time (&dev.mtime); + fs_inode_save (&dev, 1); } /* @@ -368,54 +368,54 @@ void add_device (fs_t *fs, char *name, char *spec) */ void add_file (fs_t *fs, char *name) { - fs_file_t file; - FILE *fd; - unsigned char data [BSDFS_BSIZE]; - struct stat st; - char *p; - int len; + fs_file_t file; + FILE *fd; + unsigned char data [BSDFS_BSIZE]; + struct stat st; + char *p; + int len; - if (verbose) { - printf ("%s\n", name); - } - p = strrchr (name, '/'); - if (p && p[1] == 0) { - *p = 0; - add_directory (fs, name); - return; - } - p = strrchr (name, '!'); - if (p) { - *p++ = 0; - add_device (fs, name, p); - return; - } - fd = fopen (name, "r"); - if (! fd) { - perror (name); - return; - } - stat (name, &st); - if (! fs_file_create (fs, &file, name, st.st_mode)) { - fprintf (stderr, "%s: cannot create\n", name); - return; - } - for (;;) { - len = fread (data, 1, sizeof (data), fd); -/* printf ("read %d bytes from %s\n", len, name);*/ - if (len < 0) - perror (name); - if (len <= 0) - break; - if (! fs_file_write (&file, data, len)) { - fprintf (stderr, "%s: write error\n", name); - break; - } - } - file.inode.mtime = st.st_mtime; - file.inode.dirty = 1; - fs_file_close (&file); - fclose (fd); + if (verbose) { + printf ("%s\n", name); + } + p = strrchr (name, '/'); + if (p && p[1] == 0) { + *p = 0; + add_directory (fs, name); + return; + } + p = strrchr (name, '!'); + if (p) { + *p++ = 0; + add_device (fs, name, p); + return; + } + fd = fopen (name, "r"); + if (! fd) { + perror (name); + return; + } + stat (name, &st); + if (! fs_file_create (fs, &file, name, st.st_mode)) { + fprintf (stderr, "%s: cannot create\n", name); + return; + } + for (;;) { + len = fread (data, 1, sizeof (data), fd); +/* printf ("read %d bytes from %s\n", len, name);*/ + if (len < 0) + perror (name); + if (len <= 0) + break; + if (! fs_file_write (&file, data, len)) { + fprintf (stderr, "%s: write error\n", name); + break; + } + } + file.inode.mtime = st.st_mtime; + file.inode.dirty = 1; + fs_file_close (&file); + fclose (fd); } /* @@ -424,156 +424,157 @@ void add_file (fs_t *fs, char *name) */ void add_contents (fs_t *fs, const char *dirname, const char *manifest) { - printf ("TODO: add contents from directory '%s'\n", dirname); - if (manifest) - printf ("TODO: use manifest '%s'\n", manifest); + printf ("TODO: add contents from directory '%s'\n", dirname); + if (manifest) + printf ("TODO: use manifest '%s'\n", manifest); } int main (int argc, char **argv) { - int i, key; - fs_t fs; - fs_inode_t inode; - const char *manifest = 0; + int i, key; + fs_t fs; + fs_inode_t inode; + const char *manifest = 0; - for (;;) { - key = getopt_long (argc, argv, "vaxmMn:cfs:", - program_options, 0); - if (key == -1) - break; - switch (key) { - case 'v': - ++verbose; - break; - case 'a': - ++add; - break; - case 'x': - ++extract; - break; - case 'n': - ++newfs; - kbytes = strtol (optarg, 0, 0); - break; - case 'c': - ++check; - break; - case 'f': - ++fix; - break; - case 'm': - ++mount; - break; - case 's': - swap_kbytes = strtol (optarg, 0, 0); - break; - case 'M': - manifest = optarg; - break; - case 'V': - printf ("%s\n", program_version); - return 0; - case 'h': - print_help (argv[0]); - return 0; - default: - print_help (argv[0]); - return -1; - } - } - i = optind; - if ((! add && ! mount && ! newfs && i != argc-1) || - (add && i >= argc) || - (newfs && i != argc-1 && i != argc-2) || - (mount && i != argc-2) || - (extract + newfs + check + add + mount > 1) || - (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { - print_help (argv[0]); - return -1; - } + for (;;) { + key = getopt_long (argc, argv, "vaxmMn:cfs:", + program_options, 0); + if (key == -1) + break; + switch (key) { + case 'v': + ++verbose; + break; + case 'a': + ++add; + break; + case 'x': + ++extract; + break; + case 'n': + ++newfs; + kbytes = strtol (optarg, 0, 0); + break; + case 'c': + ++check; + break; + case 'f': + ++fix; + break; + case 'm': + ++mount; + break; + case 's': + swap_kbytes = strtol (optarg, 0, 0); + break; + case 'M': + manifest = optarg; + break; + case 'V': + printf ("%s\n", program_version); + return 0; + case 'h': + print_help (argv[0]); + return 0; + default: + print_help (argv[0]); + return -1; + } + } + i = optind; + if ((! add && ! mount && ! newfs && i != argc-1) || + (add && i >= argc) || + (newfs && i != argc-1 && i != argc-2) || + (mount && i != argc-2) || + (extract + newfs + check + add + mount > 1) || + (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) + { + print_help (argv[0]); + return -1; + } - if (newfs) { - /* Create new filesystem. */ - if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { - fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); - return -1; - } - printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); + if (newfs) { + /* Create new filesystem. */ + if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { + fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); + return -1; + } + printf ("Created filesystem %s - %u kbytes\n", argv[i], kbytes); - if (i == argc-2) { - /* Add the contents from the specified directory. - * Use the optional manifest file. */ - add_contents (&fs, argv[i+1], manifest); - } - fs_close (&fs); - return 0; - } + if (i == argc-2) { + /* Add the contents from the specified directory. + * Use the optional manifest file. */ + add_contents (&fs, argv[i+1], manifest); + } + fs_close (&fs); + return 0; + } - if (check) { - /* Check filesystem for errors, and optionally fix them. */ - if (! fs_open (&fs, argv[i], fix)) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } - fs_check (&fs); - fs_close (&fs); - return 0; - } + if (check) { + /* Check filesystem for errors, and optionally fix them. */ + if (! fs_open (&fs, argv[i], fix)) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } + fs_check (&fs); + fs_close (&fs); + return 0; + } - /* Add or extract or info. */ - if (! fs_open (&fs, argv[i], (add + mount != 0))) { - fprintf (stderr, "%s: cannot open\n", argv[i]); - return -1; - } + /* Add or extract or info. */ + if (! fs_open (&fs, argv[i], (add + mount != 0))) { + fprintf (stderr, "%s: cannot open\n", argv[i]); + return -1; + } - if (extract) { - /* Extract all files to current directory. */ - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - fs_directory_scan (&inode, "", extractor, (void*) stdout); - fs_close (&fs); - return 0; - } + if (extract) { + /* Extract all files to current directory. */ + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + fs_directory_scan (&inode, "", extractor, (void*) stdout); + fs_close (&fs); + return 0; + } - if (add) { - /* Add files i+1..argc-1 to filesystem. */ - while (++i < argc) - add_file (&fs, argv[i]); - fs_sync (&fs, 0); - fs_close (&fs); - return 0; - } + if (add) { + /* Add files i+1..argc-1 to filesystem. */ + while (++i < argc) + add_file (&fs, argv[i]); + fs_sync (&fs, 0); + fs_close (&fs); + return 0; + } - if (mount) { - /* Mount the filesystem. */ - if (++i >= argc) { - print_help (argv[0]); - return -1; - } - return fs_mount(&fs, argv[i]); - } + if (mount) { + /* Mount the filesystem. */ + if (++i >= argc) { + print_help (argv[0]); + return -1; + } + return fs_mount(&fs, argv[i]); + } - /* Print the structure of flesystem. */ - fs_print (&fs, stdout); - if (verbose) { - printf ("--------\n"); - if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { - fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); - return -1; - } - printf ("/\n"); - if (verbose > 1) { - /* Print a list of blocks. */ - print_inode_blocks (&inode, stdout); - if (verbose > 2) { - fs_inode_print (&inode, stdout); - printf ("--------\n"); - } - } - fs_directory_scan (&inode, "", scanner, (void*) stdout); - } - fs_close (&fs); - return 0; + /* Print the structure of flesystem. */ + fs_print (&fs, stdout); + if (verbose) { + printf ("--------\n"); + if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { + fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); + return -1; + } + printf ("/\n"); + if (verbose > 1) { + /* Print a list of blocks. */ + print_inode_blocks (&inode, stdout); + if (verbose > 2) { + fs_inode_print (&inode, stdout); + printf ("--------\n"); + } + } + fs_directory_scan (&inode, "", scanner, (void*) stdout); + } + fs_close (&fs); + return 0; } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index ec9d88b..a07a1c5 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -32,53 +32,53 @@ extern int verbose; int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) { - unsigned long offset; - int i, reserved; + unsigned long offset; + int i, reserved; - memset (inode, 0, sizeof (*inode)); - inode->fs = fs; - inode->number = inum; + memset (inode, 0, sizeof (*inode)); + inode->fs = fs; + inode->number = inum; - /* Inodes are numbered starting from 1. - * 64 bytes per inode, 16 inodes per block. - * Skip first block. */ - if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + /* Inodes are numbered starting from 1. + * 64 bytes per inode, 16 inodes per block. + * Skip first block. */ + if (inum == 0 || inum > (fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - if (! fs_seek (fs, offset)) - return 0; + if (! fs_seek (fs, offset)) + return 0; - if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ - return 0; - if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ - return 0; - if (! fs_read32 (fs, &inode->uid)) /* owner */ - return 0; - if (! fs_read32 (fs, &inode->gid)) /* group */ - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ - return 0; + if (! fs_read16 (fs, &inode->mode)) /* file type and access mode */ + return 0; + if (! fs_read16 (fs, &inode->nlink)) /* directory entries */ + return 0; + if (! fs_read32 (fs, &inode->uid)) /* owner */ + return 0; + if (! fs_read32 (fs, &inode->gid)) /* group */ + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->size)) /* size */ + return 0; - for (i=0; iaddr[i])) - return 0; - } - if (! fs_read32 (fs, (unsigned*) &reserved)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->flags)) - return 0; - if (! fs_read32 (fs, (unsigned*) &inode->atime)) - return 0; /* last access time */ - if (! fs_read32 (fs, (unsigned*) &inode->mtime)) - return 0; /* last modification time */ - if (! fs_read32 (fs, (unsigned*) &inode->ctime)) - return 0; /* creation time */ + for (i=0; iaddr[i])) + return 0; + } + if (! fs_read32 (fs, (unsigned*) &reserved)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->flags)) + return 0; + if (! fs_read32 (fs, (unsigned*) &inode->atime)) + return 0; /* last access time */ + if (! fs_read32 (fs, (unsigned*) &inode->mtime)) + return 0; /* last modification time */ + if (! fs_read32 (fs, (unsigned*) &inode->ctime)) + return 0; /* creation time */ /*if (inode->mode) { fs_inode_print (inode, stdout); printf ("---\n"); }*/ - if (verbose > 3) - printf ("get inode %u\n", inode->number); - return 1; + if (verbose > 3) + printf ("get inode %u\n", inode->number); + return 1; } /* @@ -92,187 +92,187 @@ int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum) */ void fs_inode_truncate (fs_inode_t *inode, unsigned long size) { - int i, nblk; - unsigned *blk; + int i, nblk; + unsigned *blk; - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) - return; + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR || + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK) + return; -#define SINGLE NDADDR /* index of single indirect block */ -#define DOUBLE (SINGLE+1) /* index of double indirect block */ -#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ +#define SINGLE NDADDR /* index of single indirect block */ +#define DOUBLE (SINGLE+1) /* index of double indirect block */ +#define TRIPLE (DOUBLE+1) /* index of triple indirect block */ - nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; - for (i=TRIPLE; i>=0; --i) { - blk = &inode->addr[i]; - if (*blk == 0) - continue; + nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE; + for (i=TRIPLE; i>=0; --i) { + blk = &inode->addr[i]; + if (*blk == 0) + continue; - if (i == TRIPLE) { - if (! fs_triple_indirect_block_free (inode->fs, *blk, - nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) - break; - } else if (i == DOUBLE) { - if (! fs_double_indirect_block_free (inode->fs, *blk, - nblk - (NDADDR + BSDFS_BSIZE/4))) - break; - } else if (i == SINGLE) { - if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) - break; - } else { - if (i * BSDFS_BSIZE < size) - break; - fs_block_free (inode->fs, *blk); - } + if (i == TRIPLE) { + if (! fs_triple_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4))) + break; + } else if (i == DOUBLE) { + if (! fs_double_indirect_block_free (inode->fs, *blk, + nblk - (NDADDR + BSDFS_BSIZE/4))) + break; + } else if (i == SINGLE) { + if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR)) + break; + } else { + if (i * BSDFS_BSIZE < size) + break; + fs_block_free (inode->fs, *blk); + } - *blk = 0; - } + *blk = 0; + } - inode->size = size; - inode->dirty = 1; + inode->size = size; + inode->dirty = 1; } void fs_inode_clear (fs_inode_t *inode) { - inode->dirty = 1; - inode->mode = 0; - inode->nlink = 0; - inode->uid = 0; - inode->size = 0; - memset (inode->addr, 0, sizeof(inode->addr)); - inode->atime = 0; - inode->mtime = 0; + inode->dirty = 1; + inode->mode = 0; + inode->nlink = 0; + inode->uid = 0; + inode->size = 0; + memset (inode->addr, 0, sizeof(inode->addr)); + inode->atime = 0; + inode->mtime = 0; } int fs_inode_save (fs_inode_t *inode, int force) { - unsigned long offset; - int i; + unsigned long offset; + int i; - if (! inode->fs->writable) - return 0; - if (! force && ! inode->dirty) - return 1; - if (inode->number == 0 || - inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) - return 0; - offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * - BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; + if (! inode->fs->writable) + return 0; + if (! force && ! inode->dirty) + return 1; + if (inode->number == 0 || + inode->number > (inode->fs->isize-1) * BSDFS_INODES_PER_BLOCK) + return 0; + offset = (inode->number + BSDFS_INODES_PER_BLOCK - 1) * + BSDFS_BSIZE / BSDFS_INODES_PER_BLOCK; - time (&inode->atime); + time (&inode->atime); - if (! fs_seek (inode->fs, offset)) - return 0; + if (! fs_seek (inode->fs, offset)) + return 0; - if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ - return 0; - if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ - return 0; - if (! fs_write32 (inode->fs, inode->uid)) /* owner */ - return 0; - if (! fs_write32 (inode->fs, inode->gid)) /* group */ - return 0; - if (! fs_write32 (inode->fs, inode->size)) /* size */ - return 0; + if (! fs_write16 (inode->fs, inode->mode)) /* file type and access mode */ + return 0; + if (! fs_write16 (inode->fs, inode->nlink)) /* directory entries */ + return 0; + if (! fs_write32 (inode->fs, inode->uid)) /* owner */ + return 0; + if (! fs_write32 (inode->fs, inode->gid)) /* group */ + return 0; + if (! fs_write32 (inode->fs, inode->size)) /* size */ + return 0; - for (i=0; ifs, inode->addr[i])) - return 0; - } - if (! fs_write32 (inode->fs, 0)) /* reserved */ - return 0; - if (! fs_write32 (inode->fs, inode->flags)) /* flags */ - return 0; - if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ - return 0; - if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ - return 0; - if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ - return 0; + for (i=0; ifs, inode->addr[i])) + return 0; + } + if (! fs_write32 (inode->fs, 0)) /* reserved */ + return 0; + if (! fs_write32 (inode->fs, inode->flags)) /* flags */ + return 0; + if (! fs_write32 (inode->fs, inode->atime)) /* last access time */ + return 0; + if (! fs_write32 (inode->fs, inode->mtime)) /* last modification time */ + return 0; + if (! fs_write32 (inode->fs, inode->ctime)) /* creation time */ + return 0; - inode->dirty = 0; - if (verbose > 3) - printf ("save inode %u\n", inode->number); - return 1; + inode->dirty = 0; + if (verbose > 3) + printf ("save inode %u\n", inode->number); + return 1; } void fs_inode_print (fs_inode_t *inode, FILE *out) { - int i; + int i; - fprintf (out, " I-node: %u\n", inode->number); - fprintf (out, " Type: %s\n", - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : - (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : - "Unknown"); - fprintf (out, " Size: %lu bytes\n", inode->size); - fprintf (out, " Mode: %#o\n", inode->mode); + fprintf (out, " I-node: %u\n", inode->number); + fprintf (out, " Type: %s\n", + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR ? "Directory" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ? "Character device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK ? "Block device" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FREG ? "File" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FLNK ? "Symbolic link" : + (inode->mode & INODE_MODE_FMT) == INODE_MODE_FSOCK? "Socket" : + "Unknown"); + fprintf (out, " Size: %lu bytes\n", inode->size); + fprintf (out, " Mode: %#o\n", inode->mode); - fprintf (out, " "); - if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); - if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); - if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); - if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); - if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); - if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); - fprintf (out, "\n"); + fprintf (out, " "); + if (inode->mode & INODE_MODE_SUID) fprintf (out, " SUID"); + if (inode->mode & INODE_MODE_SGID) fprintf (out, " SGID"); + if (inode->mode & INODE_MODE_SVTX) fprintf (out, " SVTX"); + if (inode->mode & INODE_MODE_READ) fprintf (out, " READ"); + if (inode->mode & INODE_MODE_WRITE) fprintf (out, " WRITE"); + if (inode->mode & INODE_MODE_EXEC) fprintf (out, " EXEC"); + fprintf (out, "\n"); - fprintf (out, " Links: %u\n", inode->nlink); - fprintf (out, " Owner id: %u\n", inode->uid); + fprintf (out, " Links: %u\n", inode->nlink); + fprintf (out, " Owner id: %u\n", inode->uid); - fprintf (out, " Blocks:"); - for (i=0; iaddr[i]); - } - fprintf (out, "\n"); + fprintf (out, " Blocks:"); + for (i=0; iaddr[i]); + } + fprintf (out, "\n"); - fprintf (out, " Created: %s", ctime (&inode->ctime)); - fprintf (out, " Modified: %s", ctime (&inode->mtime)); - fprintf (out, "Last access: %s", ctime (&inode->atime)); + fprintf (out, " Created: %s", ctime (&inode->ctime)); + fprintf (out, " Modified: %s", ctime (&inode->mtime)); + fprintf (out, "Last access: %s", ctime (&inode->atime)); } void fs_directory_scan (fs_inode_t *dir, char *dirname, - fs_directory_scanner_t scanner, void *arg) + fs_directory_scanner_t scanner, void *arg) { - fs_inode_t file; - unsigned long offset; - unsigned char name [BSDFS_BSIZE - 12]; - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - } dirent; + fs_inode_t file; + unsigned long offset; + unsigned char name [BSDFS_BSIZE - 12]; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; - /* Variable record per file */ - for (offset = 0; offset < dir->size; offset += dirent.reclen) { - if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "%s: read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + /* Variable record per file */ + for (offset = 0; offset < dir->size; offset += dirent.reclen) { + if (! fs_inode_read (dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "%s: read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen);*/ - if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { - fprintf (stderr, "%s: name read error at offset %ld\n", - dirname[0] ? dirname : "/", offset); - return; - } + if (! fs_inode_read (dir, offset+sizeof(dirent), name, (dirent.namlen + 4) / 4 * 4)) { + fprintf (stderr, "%s: name read error at offset %ld\n", + dirname[0] ? dirname : "/", offset); + return; + } /*printf ("scan offset %lu: name='%s'\n", offset, name);*/ - if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || - (name[0]=='.' && name[1]=='.' && name[2]==0)) - continue; + if (dirent.inum == 0 || (name[0]=='.' && name[1]==0) || + (name[0]=='.' && name[1]=='.' && name[2]==0)) + continue; - if (! fs_inode_get (dir->fs, &file, dirent.inum)) { - fprintf (stderr, "cannot scan inode %d\n", dirent.inum); - continue; - } - scanner (dir, &file, dirname, (char*) name, arg); - } + if (! fs_inode_get (dir->fs, &file, dirent.inum)) { + fprintf (stderr, "cannot scan inode %d\n", dirent.inum); + continue; + } + scanner (dir, &file, dirname, (char*) name, arg); + } } /* @@ -281,57 +281,57 @@ void fs_directory_scan (fs_inode_t *dir, char *dirname, */ static unsigned map_block (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, i, j, sh; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, i, j, sh; - /* - * Blocks 0..NADDR-4 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - return inode->addr [lbn]; - } + /* + * Blocks 0..NADDR-4 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + return inode->addr [lbn]; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) - return 0; + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) + return 0; - /* - * Fetch through the indirect blocks. - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks. + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - nb = block [i]; - if (nb == 0) - return 0; - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + nb = block [i]; + if (nb == 0) + return 0; + } + return nb; } /* @@ -341,163 +341,163 @@ static unsigned map_block (fs_inode_t *inode, unsigned lbn) */ static unsigned map_block_write (fs_inode_t *inode, unsigned lbn) { - unsigned block [BSDFS_BSIZE / 4]; - unsigned int nb, newb, sh, i, j; + unsigned block [BSDFS_BSIZE / 4]; + unsigned int nb, newb, sh, i, j; - /* - * Blocks 0..NADDR-3 are direct blocks. - */ - if (lbn < NADDR-3) { - /* small file algorithm */ - nb = inode->addr [lbn]; - if (nb != 0) { - if (verbose) - printf ("map logical block %d to physical %d\n", lbn, nb); - return nb; - } + /* + * Blocks 0..NADDR-3 are direct blocks. + */ + if (lbn < NADDR-3) { + /* small file algorithm */ + nb = inode->addr [lbn]; + if (nb != 0) { + if (verbose) + printf ("map logical block %d to physical %d\n", lbn, nb); + return nb; + } - /* allocate new block */ - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - inode->addr[lbn] = nb; - inode->dirty = 1; - return nb; - } + /* allocate new block */ + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + inode->addr[lbn] = nb; + inode->dirty = 1; + return nb; + } - /* - * Addresses NADDR-3, NADDR-2, and NADDR-1 - * have single, double, triple indirect blocks. - * The first step is to determine - * how many levels of indirection. - */ - sh = 0; - nb = 1; - lbn -= NADDR-3; - for (j=3; ; j--) { - if (j == 0) - return 0; - sh += NSHIFT; - nb <<= NSHIFT; - if (lbn < nb) - break; - lbn -= nb; - } + /* + * Addresses NADDR-3, NADDR-2, and NADDR-1 + * have single, double, triple indirect blocks. + * The first step is to determine + * how many levels of indirection. + */ + sh = 0; + nb = 1; + lbn -= NADDR-3; + for (j=3; ; j--) { + if (j == 0) + return 0; + sh += NSHIFT; + nb <<= NSHIFT; + if (lbn < nb) + break; + lbn -= nb; + } - /* - * Fetch the first indirect block. - */ - nb = inode->addr [NADDR-j]; - if (nb == 0) { - if (! fs_block_alloc (inode->fs, &nb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, nb); - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - inode->addr [NADDR-j] = nb; - inode->dirty = 1; - } + /* + * Fetch the first indirect block. + */ + nb = inode->addr [NADDR-j]; + if (nb == 0) { + if (! fs_block_alloc (inode->fs, &nb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, nb); + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + inode->addr [NADDR-j] = nb; + inode->dirty = 1; + } - /* - * Fetch through the indirect blocks - */ - for(; j <= 3; j++) { - if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) - return 0; + /* + * Fetch through the indirect blocks + */ + for(; j <= 3; j++) { + if (! fs_read_block (inode->fs, nb, (unsigned char*) block)) + return 0; - sh -= NSHIFT; - i = (lbn >> sh) & NMASK; - if (block [i] != 0) - nb = block [i]; - else { - /* Allocate new block. */ - if (! fs_block_alloc (inode->fs, &newb)) - return 0; - if (verbose) - printf ("inode %d: allocate new block %d\n", inode->number, newb); - block[i] = newb; - if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) - return 0; - memset (block, 0, BSDFS_BSIZE); - if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) - return 0; - nb = newb; - } - } - return nb; + sh -= NSHIFT; + i = (lbn >> sh) & NMASK; + if (block [i] != 0) + nb = block [i]; + else { + /* Allocate new block. */ + if (! fs_block_alloc (inode->fs, &newb)) + return 0; + if (verbose) + printf ("inode %d: allocate new block %d\n", inode->number, newb); + block[i] = newb; + if (! fs_write_block (inode->fs, nb, (unsigned char*) block)) + return 0; + memset (block, 0, BSDFS_BSIZE); + if (! fs_write_block (inode->fs, newb, (unsigned char*) block)) + return 0; + nb = newb; + } + } + return nb; } int fs_inode_read (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - if (bytes + offset > inode->size) - return 0; - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + if (bytes + offset > inode->size) + return 0; + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; + bn = map_block (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (data, block + inblock_offset, n); - data += n; - offset += n; - bytes -= n; - } - return 1; + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (data, block + inblock_offset, n); + data += n; + offset += n; + bytes -= n; + } + return 1; } int fs_inode_write (fs_inode_t *inode, unsigned long offset, - unsigned char *data, unsigned long bytes) + unsigned char *data, unsigned long bytes) { - unsigned char block [BSDFS_BSIZE]; - unsigned long n; - unsigned int bn, inblock_offset; + unsigned char block [BSDFS_BSIZE]; + unsigned long n; + unsigned int bn, inblock_offset; - time (&inode->mtime); - while (bytes != 0) { - inblock_offset = offset % BSDFS_BSIZE; - n = BSDFS_BSIZE - inblock_offset; - if (n > bytes) - n = bytes; + time (&inode->mtime); + while (bytes != 0) { + inblock_offset = offset % BSDFS_BSIZE; + n = BSDFS_BSIZE - inblock_offset; + if (n > bytes) + n = bytes; - bn = map_block_write (inode, offset / BSDFS_BSIZE); - if (bn == 0) - return 0; - if (inode->size < offset + n) { - /* Increase file size. */ - inode->size = offset + n; - inode->dirty = 1; - } - if (verbose) - printf ("inode %d offset %ld: write %ld bytes to block %d\n", - inode->number, offset, n, bn); + bn = map_block_write (inode, offset / BSDFS_BSIZE); + if (bn == 0) + return 0; + if (inode->size < offset + n) { + /* Increase file size. */ + inode->size = offset + n; + inode->dirty = 1; + } + if (verbose) + printf ("inode %d offset %ld: write %ld bytes to block %d\n", + inode->number, offset, n, bn); - if (n == BSDFS_BSIZE) { - if (! fs_write_block (inode->fs, bn, data)) - return 0; - } else { - if (! fs_read_block (inode->fs, bn, block)) - return 0; - memcpy (block + inblock_offset, data, n); - if (! fs_write_block (inode->fs, bn, block)) - return 0; - } - data += n; - offset += n; - bytes -= n; - } - return 1; + if (n == BSDFS_BSIZE) { + if (! fs_write_block (inode->fs, bn, data)) + return 0; + } else { + if (! fs_read_block (inode->fs, bn, block)) + return 0; + memcpy (block + inblock_offset, data, n); + if (! fs_write_block (inode->fs, bn, block)) + return 0; + } + data += n; + offset += n; + bytes -= n; + } + return 1; } /* @@ -505,20 +505,20 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, */ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) { - int i; + int i; - *data++ = dirent->ino; - *data++ = dirent->ino >> 8; - *data++ = dirent->ino >> 16; - *data++ = dirent->ino >> 24; - *data++ = dirent->reclen; - *data++ = dirent->reclen >> 8; - *data++ = dirent->namlen; - *data++ = dirent->namlen >> 8; - for (i=0; dirent->name[i]; ++i) - *data++ = dirent->name[i]; - for (; i & 3; ++i) - *data++ = 0; + *data++ = dirent->ino; + *data++ = dirent->ino >> 8; + *data++ = dirent->ino >> 16; + *data++ = dirent->ino >> 24; + *data++ = dirent->reclen; + *data++ = dirent->reclen >> 8; + *data++ = dirent->namlen; + *data++ = dirent->namlen >> 8; + for (i=0; dirent->name[i]; ++i) + *data++ = dirent->name[i]; + for (; i & 3; ++i) + *data++ = 0; } /* @@ -526,16 +526,16 @@ void fs_dirent_pack (unsigned char *data, fs_dirent_t *dirent) */ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) { - dirent->ino = *data++; - dirent->ino |= *data++ << 8; - dirent->ino |= *data++ << 16; - dirent->ino |= *data++ << 24; - dirent->reclen = *data++; - dirent->reclen |= *data++ << 8; - dirent->namlen = *data++; - dirent->namlen |= *data++ << 8; - memset (dirent->name, 0, sizeof (dirent->name)); - memcpy (dirent->name, data, dirent->namlen); + dirent->ino = *data++; + dirent->ino |= *data++ << 8; + dirent->ino |= *data++ << 16; + dirent->ino |= *data++ << 24; + dirent->reclen = *data++; + dirent->reclen |= *data++ << 8; + dirent->namlen = *data++; + dirent->namlen |= *data++ << 8; + memset (dirent->name, 0, sizeof (dirent->name)); + memcpy (dirent->name, data, dirent->namlen); } /* @@ -543,276 +543,276 @@ void fs_dirent_unpack (fs_dirent_t *dirent, unsigned char *data) * an inode. Note that the inode is locked. * * op = 0 if name is saught - * 1 if name is to be created, mode is given - * 2 if name is to be deleted - * 3 if name is to be linked, mode contains inode number + * 1 if name is to be created, mode is given + * 2 if name is to be deleted + * 3 if name is to be linked, mode contains inode number * * Return 0 on any error. * Return 1 when the inode was found. * Return 2 when the inode was created/deleted/linked. */ int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, - fs_op_t op, int mode) + fs_op_t op, int mode) { - fs_inode_t dir; - int c, namlen, reclen; - const char *namptr; - unsigned long offset, last_offset; - struct { + fs_inode_t dir; + int c, namlen, reclen; + const char *namptr; + unsigned long offset, last_offset; + struct { + unsigned int inum; + unsigned short reclen; + unsigned short namlen; + } dirent; + + /* Start from root. */ + if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { + fprintf (stderr, "inode_open(): cannot get root\n"); + return 0; + } + c = *name++; + while (c == '/') + c = *name++; + if (! c && op != INODE_OP_LOOKUP) { + /* Cannot write or delete root directory. */ + return 0; + } +cloop: + /* Here inode contains pointer + * to last component matched. */ + if (! c) { + *inode = dir; + return 1; + } + + /* If there is another component, + * inode must be a directory. */ + if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { + return 0; + } + + /* Gather up dir name into buffer. */ + namptr = name - 1; + while (c && c != '/') { + c = *name++; + } + namlen = name - namptr - 1; + while (c == '/') + c = *name++; + + /* Search a directory, variable record per file */ + if (verbose > 2) + printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); + last_offset = 0; + for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { + unsigned char fname [BSDFS_BSIZE - 12]; + + if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); + if (dirent.inum == 0 || dirent.namlen != namlen) + continue; + if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { + fprintf (stderr, "inode %d: name read error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); + if (strncmp (namptr, (char*) fname, namlen) == 0) { + /* Here a component matched in a directory. + * If there is more pathname, go back to + * cloop, otherwise return. */ + if (op == INODE_OP_DELETE && ! c) { + goto delete_file; + } + if (! fs_inode_get (fs, &dir, dirent.inum)) { + fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); + return 0; + } + goto cloop; + } + } + /* If at the end of the directory, the search failed. + * Report what is appropriate as per flag. */ + if (op == INODE_OP_CREATE && ! c) + goto create_file; + if (op == INODE_OP_LINK && ! c) + goto create_link; + return 0; + + /* + * Make a new file, and return it's inode. + */ +create_file: + if (! fs_inode_alloc (fs, inode)) { + fprintf (stderr, "%s: cannot allocate inode\n", namptr); + return 0; + } + inode->dirty = 1; + inode->mode = mode & (07777 | INODE_MODE_FMT); + if ((inode->mode & INODE_MODE_FMT) == 0) + inode->mode |= INODE_MODE_FREG; + inode->nlink = 1; + inode->uid = 0; + inode->flags = 0; + time (&inode->ctime); + if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + /* Make link '.' */ + struct { unsigned int inum; unsigned short reclen; unsigned short namlen; - } dirent; - - /* Start from root. */ - if (! fs_inode_get (fs, &dir, BSDFS_ROOT_INODE)) { - fprintf (stderr, "inode_open(): cannot get root\n"); - return 0; - } - c = *name++; - while (c == '/') - c = *name++; - if (! c && op != INODE_OP_LOOKUP) { - /* Cannot write or delete root directory. */ - return 0; - } -cloop: - /* Here inode contains pointer - * to last component matched. */ - if (! c) { - *inode = dir; - return 1; - } - - /* If there is another component, - * inode must be a directory. */ - if ((dir.mode & INODE_MODE_FMT) != INODE_MODE_FDIR) { - return 0; - } - - /* Gather up dir name into buffer. */ - namptr = name - 1; - while (c && c != '/') { - c = *name++; - } - namlen = name - namptr - 1; - while (c == '/') - c = *name++; - - /* Search a directory, variable record per file */ - if (verbose > 2) - printf ("scan for '%.*s', %d bytes\n", namlen, namptr, namlen); - last_offset = 0; - for (offset = 0; offset < dir.size; last_offset = offset, offset += dirent.reclen) { - unsigned char fname [BSDFS_BSIZE - 12]; - - if (! fs_inode_read (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: inum=%u, reclen=%u, namlen=%u\n", offset, dirent.inum, dirent.reclen, dirent.namlen); - if (dirent.inum == 0 || dirent.namlen != namlen) - continue; - if (! fs_inode_read (&dir, offset+sizeof(dirent), fname, namlen)) { - fprintf (stderr, "inode %d: name read error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("scan offset %lu: name='%.*s'\n", offset, namlen, fname); - if (strncmp (namptr, (char*) fname, namlen) == 0) { - /* Here a component matched in a directory. - * If there is more pathname, go back to - * cloop, otherwise return. */ - if (op == INODE_OP_DELETE && ! c) { - goto delete_file; - } - if (! fs_inode_get (fs, &dir, dirent.inum)) { - fprintf (stderr, "inode_open(): cannot get inode %d\n", dirent.inum); - return 0; - } - goto cloop; - } - } - /* If at the end of the directory, the search failed. - * Report what is appropriate as per flag. */ - if (op == INODE_OP_CREATE && ! c) - goto create_file; - if (op == INODE_OP_LINK && ! c) - goto create_link; - return 0; - - /* - * Make a new file, and return it's inode. - */ -create_file: - if (! fs_inode_alloc (fs, inode)) { - fprintf (stderr, "%s: cannot allocate inode\n", namptr); - return 0; - } - inode->dirty = 1; - inode->mode = mode & (07777 | INODE_MODE_FMT); - if ((inode->mode & INODE_MODE_FMT) == 0) - inode->mode |= INODE_MODE_FREG; - inode->nlink = 1; - inode->uid = 0; - inode->flags = 0; - time (&inode->ctime); - if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { - /* Make link '.' */ - struct { - unsigned int inum; - unsigned short reclen; - unsigned short namlen; - char name [4]; - } dotent; - dotent.inum = inode->number; - dotent.reclen = BSDFS_BSIZE; - dotent.namlen = 1; - memcpy (dotent.name, ".\0\0\0", 4); - if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - inode->number, 0L); - return 0; - } - /* Increase file size. */ - inode->size = BSDFS_BSIZE; - ++inode->nlink; + char name [4]; + } dotent; + dotent.inum = inode->number; + dotent.reclen = BSDFS_BSIZE; + dotent.namlen = 1; + memcpy (dotent.name, ".\0\0\0", 4); + if (! fs_inode_write (inode, 0, (unsigned char*) &dotent, sizeof(dotent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + inode->number, 0L); + return 0; } - if (! fs_inode_save (inode, 0)) { - fprintf (stderr, "%s: cannot save file inode\n", namptr); - return 0; - } + /* Increase file size. */ + inode->size = BSDFS_BSIZE; + ++inode->nlink; + } + if (! fs_inode_save (inode, 0)) { + fprintf (stderr, "%s: cannot save file inode\n", namptr); + return 0; + } - /* Write a directory entry. */ - if (verbose > 2) - printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; - c = 8 + (namlen + 4) / 4 * 4; - if (reclen >= c) { - /* Enough space */ - dirent.reclen -= reclen; - if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - } else { - /* No space, extend directory. */ - if (verbose > 2) - printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", - dirent.inum, dirent.reclen, dirent.namlen, last_offset); - reclen = BSDFS_BSIZE; - } - offset = last_offset + dirent.reclen; - dirent.inum = inode->number; - dirent.reclen = reclen; - dirent.namlen = namlen; - if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - /* Align directory size. */ - dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - return 2; - - /* - * Delete file. Return inode of deleted file. - */ -delete_file: - if (verbose > 2) - printf ("*** delete inode %d\n", dirent.inum); - if (! fs_inode_get (fs, inode, dirent.inum)) { - fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); - return 0; - } - inode->dirty = 1; - inode->nlink--; - if (inode->nlink <= 0) { - fs_inode_truncate (inode, 0); - fs_inode_clear (inode); - if (inode->fs->ninode < NICINOD) { - inode->fs->inode [inode->fs->ninode++] = dirent.inum; - inode->fs->dirty = 1; - } - } - /* Extend previous entry to cover the empty space. */ - reclen = dirent.reclen; - if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: read error at offset %ld\n", - dir.number, last_offset); - return 0; - } - dirent.reclen += reclen; - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - return 2; - - /* - * Make a link. Return a directory inode. - */ -create_link: - if (verbose > 2) - printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); - reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + /* Write a directory entry. */ + if (verbose > 2) + printf ("*** create file '%.*s', inode %d\n", namlen, namptr, inode->number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + c = 8 + (namlen + 4) / 4 * 4; + if (reclen >= c) { + /* Enough space */ dirent.reclen -= reclen; if (verbose > 2) - printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); - if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, last_offset); - return 0; - } - offset = last_offset + dirent.reclen; - dirent.inum = mode; - dirent.reclen = reclen; - dirent.namlen = namlen; + printf ("*** previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + } else { + /* No space, extend directory. */ if (verbose > 2) - printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); - if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset); - return 0; - } - if (verbose > 2) - printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); - if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { - fprintf (stderr, "inode %d: write error at offset %ld\n", - dir.number, offset+sizeof(dirent)); - return 0; - } - if (! fs_inode_save (&dir, 0)) { - fprintf (stderr, "%s: cannot save directory inode\n", namptr); - return 0; - } - *inode = dir; - return 2; + printf ("*** extend dir, previous entry %u-%u-%u at offset %lu\n", + dirent.inum, dirent.reclen, dirent.namlen, last_offset); + reclen = BSDFS_BSIZE; + } + offset = last_offset + dirent.reclen; + dirent.inum = inode->number; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + /* Align directory size. */ + dir.size = (dir.size + BSDFS_BSIZE - 1) / BSDFS_BSIZE * BSDFS_BSIZE; + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Delete file. Return inode of deleted file. + */ +delete_file: + if (verbose > 2) + printf ("*** delete inode %d\n", dirent.inum); + if (! fs_inode_get (fs, inode, dirent.inum)) { + fprintf (stderr, "%s: cannot get inode %d\n", namptr, dirent.inum); + return 0; + } + inode->dirty = 1; + inode->nlink--; + if (inode->nlink <= 0) { + fs_inode_truncate (inode, 0); + fs_inode_clear (inode); + if (inode->fs->ninode < NICINOD) { + inode->fs->inode [inode->fs->ninode++] = dirent.inum; + inode->fs->dirty = 1; + } + } + /* Extend previous entry to cover the empty space. */ + reclen = dirent.reclen; + if (! fs_inode_read (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: read error at offset %ld\n", + dir.number, last_offset); + return 0; + } + dirent.reclen += reclen; + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + return 2; + + /* + * Make a link. Return a directory inode. + */ +create_link: + if (verbose > 2) + printf ("*** link inode %d to '%.*s', directory %d\n", mode, namlen, namptr, dir.number); + reclen = dirent.reclen - 8 - (dirent.namlen + 4) / 4 * 4; + dirent.reclen -= reclen; + if (verbose > 2) + printf ("*** previous entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, last_offset); + if (! fs_inode_write (&dir, last_offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, last_offset); + return 0; + } + offset = last_offset + dirent.reclen; + dirent.inum = mode; + dirent.reclen = reclen; + dirent.namlen = namlen; + if (verbose > 2) + printf ("*** new entry %u-%u-%u at offset %lu\n", dirent.inum, dirent.reclen, dirent.namlen, offset); + if (! fs_inode_write (&dir, offset, (unsigned char*) &dirent, sizeof(dirent))) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset); + return 0; + } + if (verbose > 2) + printf ("*** name '%.*s' at offset %lu\n", namlen, namptr, offset+sizeof(dirent)); + if (! fs_inode_write (&dir, offset+sizeof(dirent), (unsigned char*) namptr, namlen)) { + fprintf (stderr, "inode %d: write error at offset %ld\n", + dir.number, offset+sizeof(dirent)); + return 0; + } + if (! fs_inode_save (&dir, 0)) { + fprintf (stderr, "%s: cannot save directory inode\n", namptr); + return 0; + } + *inode = dir; + return 2; } /* @@ -824,30 +824,30 @@ create_link: */ int fs_inode_alloc (fs_t *fs, fs_inode_t *inode) { - int ino; + int ino; - for (;;) { - if (fs->ninode <= 0) { - /* Build a list of free inodes. */ - if (! inode_build_list (fs)) { - fprintf (stderr, "inode_alloc: cannot build inode list\n"); - return 0; - } - if (fs->ninode <= 0) { - fprintf (stderr, "inode_alloc: out of in-core inodes\n"); - return 0; - } - } - ino = fs->inode[--fs->ninode]; - fs->dirty = 1; - fs->tinode--; - if (! fs_inode_get (fs, inode, ino)) { - fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); - return 0; - } - if (inode->mode == 0) { - fs_inode_clear (inode); - return 1; - } - } + for (;;) { + if (fs->ninode <= 0) { + /* Build a list of free inodes. */ + if (! inode_build_list (fs)) { + fprintf (stderr, "inode_alloc: cannot build inode list\n"); + return 0; + } + if (fs->ninode <= 0) { + fprintf (stderr, "inode_alloc: out of in-core inodes\n"); + return 0; + } + } + ino = fs->inode[--fs->ninode]; + fs->dirty = 1; + fs->tinode--; + if (! fs_inode_get (fs, inode, ino)) { + fprintf (stderr, "inode_alloc: cannot get inode %d\n", ino); + return 0; + } + if (inode->mode == 0) { + fs_inode_clear (inode); + return 1; + } + } } diff --git a/tools/fsutil/superblock.c b/tools/fsutil/superblock.c index aa1d373..cc96ef7 100644 --- a/tools/fsutil/superblock.c +++ b/tools/fsutil/superblock.c @@ -32,298 +32,300 @@ extern int verbose; int fs_seek (fs_t *fs, unsigned long offset) { -/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ - if (lseek (fs->fd, offset, 0) < 0) { - if (verbose) - printf ("error seeking %ld, block %ld\n", - offset, offset / BSDFS_BSIZE); - return 0; - } - fs->seek = offset; - return 1; +/* printf ("seek %ld, block %ld\n", offset, offset / BSDFS_BSIZE);*/ + if (lseek (fs->fd, offset, 0) < 0) { + if (verbose) + printf ("error seeking %ld, block %ld\n", + offset, offset / BSDFS_BSIZE); + return 0; + } + fs->seek = offset; + return 1; } int fs_read8 (fs_t *fs, unsigned char *val) { - if (read (fs->fd, val, 1) != 1) { - if (verbose) - printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - return 1; + if (read (fs->fd, val, 1) != 1) { + if (verbose) + printf ("error read8, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + return 1; } int fs_read16 (fs_t *fs, unsigned short *val) { - unsigned char data [2]; + unsigned char data [2]; - if (read (fs->fd, data, 2) != 2) { - if (verbose) - printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = data[1] << 8 | data[0]; - return 1; + if (read (fs->fd, data, 2) != 2) { + if (verbose) + printf ("error read16, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = data[1] << 8 | data[0]; + return 1; } int fs_read32 (fs_t *fs, unsigned *val) { - unsigned char data [4]; + unsigned char data [4]; - if (read (fs->fd, data, 4) != 4) { - if (verbose) - printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); - return 0; - } - *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | - data[2] << 16 | data[3] << 24; - return 1; + if (read (fs->fd, data, 4) != 4) { + if (verbose) + printf ("error read32, seek %ld block %ld\n", fs->seek, fs->seek / BSDFS_BSIZE); + return 0; + } + *val = (unsigned long) data[0] | (unsigned long) data[1] << 8 | + data[2] << 16 | data[3] << 24; + return 1; } int fs_write8 (fs_t *fs, unsigned char val) { - if (write (fs->fd, &val, 1) != 1) - return 0; - return 1; + if (write (fs->fd, &val, 1) != 1) + return 0; + return 1; } int fs_write16 (fs_t *fs, unsigned short val) { - unsigned char data [2]; + unsigned char data [2]; - data[0] = val; - data[1] = val >> 8; - if (write (fs->fd, data, 2) != 2) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + if (write (fs->fd, data, 2) != 2) + return 0; + return 1; } int fs_write32 (fs_t *fs, unsigned val) { - unsigned char data [4]; + unsigned char data [4]; - data[0] = val; - data[1] = val >> 8; - data[2] = val >> 16; - data[3] = val >> 24; - if (write (fs->fd, data, 4) != 4) - return 0; - return 1; + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; + if (write (fs->fd, data, 4) != 4) + return 0; + return 1; } int fs_read (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (read (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (read (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_write (fs_t *fs, unsigned char *data, int bytes) { - int len; + int len; - if (! fs->writable) - return 0; - while (bytes > 0) { - len = bytes; - if (len > 16*BSDFS_BSIZE) - len = 16*BSDFS_BSIZE; - if (write (fs->fd, data, len) != len) - return 0; - data += len; - bytes -= len; - } - return 1; + if (! fs->writable) + return 0; + while (bytes > 0) { + len = bytes; + if (len > 16*BSDFS_BSIZE) + len = 16*BSDFS_BSIZE; + if (write (fs->fd, data, len) != len) + return 0; + data += len; + bytes -= len; + } + return 1; } int fs_open (fs_t *fs, const char *filename, int writable) { - int i; - unsigned magic; + int i; + unsigned magic; - memset (fs, 0, sizeof (*fs)); - fs->filename = filename; - fs->seek = 0; + memset (fs, 0, sizeof (*fs)); + fs->filename = filename; + fs->seek = 0; - fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); - if (fs->fd < 0) - return 0; - fs->writable = writable; + fs->fd = open (fs->filename, writable ? O_RDWR : O_RDONLY); + if (fs->fd < 0) + return 0; + fs->writable = writable; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC1) { - if (verbose) - printf ("fs_open: bad magic1 = %08x, expected %08x\n", - magic, FSMAGIC1); - return 0; - } - if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_read32 (fs, &fs->flock)) - return 0; - if (! fs_read32 (fs, &fs->fmod)) - return 0; - if (! fs_read32 (fs, &fs->ilock)) - return 0; - if (! fs_read32 (fs, &fs->ronly)) - return 0; - if (! fs_read32 (fs, (unsigned*) &fs->utime)) - return 0; /* current date of last update */ - if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ - return 0; - if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ - return 0; - if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ - return 0; - if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ - return 0; - if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ - return 0; - if (! fs_read32 (fs, &magic) || /* magic word */ - magic != FSMAGIC2) { - if (verbose) - printf ("fs_open: bad magic2 = %08x, expected %08x\n", - magic, FSMAGIC2); - return 0; - } - return 1; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC1) { + if (verbose) + printf ("fs_open: bad magic1 = %08x, expected %08x\n", + magic, FSMAGIC1); + return 0; + } + if (! fs_read32 (fs, &fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_read32 (fs, &fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_read32 (fs, &fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_read32 (fs, &fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_read32 (fs, &fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_read32 (fs, &fs->flock)) + return 0; + if (! fs_read32 (fs, &fs->fmod)) + return 0; + if (! fs_read32 (fs, &fs->ilock)) + return 0; + if (! fs_read32 (fs, &fs->ronly)) + return 0; + if (! fs_read32 (fs, (unsigned*) &fs->utime)) + return 0; /* current date of last update */ + if (! fs_read32 (fs, &fs->tfree)) /* total free blocks */ + return 0; + if (! fs_read32 (fs, &fs->tinode)) /* total free inodes */ + return 0; + if (! fs_read (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_read32 (fs, &fs->lasti)) /* start place for circular search */ + return 0; + if (! fs_read32 (fs, &fs->nbehind)) /* est # free inodes before s_lasti */ + return 0; + if (! fs_read32 (fs, &fs->flags)) /* mount time flags */ + return 0; + if (! fs_read32 (fs, &magic) || /* magic word */ + magic != FSMAGIC2) { + if (verbose) + printf ("fs_open: bad magic2 = %08x, expected %08x\n", + magic, FSMAGIC2); + return 0; + } + return 1; } int fs_sync (fs_t *fs, int force) { - int i; + int i; - if (! fs->writable) - return 0; - if (! force && ! fs->dirty) - return 1; + if (! fs->writable) + return 0; + if (! force && ! fs->dirty) + return 1; - time (&fs->utime); - if (! fs_seek (fs, 0)) - return 0; + time (&fs->utime); + if (! fs_seek (fs, 0)) + return 0; - if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ - return 0; - if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ - return 0; - if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ - return 0; - if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ - return 0; - if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ - return 0; - for (i=0; ifree[i])) - return 0; - } - if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ - return 0; - for (i=0; iinode[i])) - return 0; - } - if (! fs_write32 (fs, fs->flock)) - return 0; - if (! fs_write32 (fs, fs->fmod)) - return 0; - if (! fs_write32 (fs, fs->ilock)) - return 0; - if (! fs_write32 (fs, fs->ronly)) - return 0; - if (! fs_write32 (fs, fs->utime)) /* current date of last update */ - return 0; - if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ - return 0; - if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ - return 0; - if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) - return 0; /* ordinary file mounted on */ - if (! fs_write32 (fs, 0)) /* lasti*/ - return 0; - if (! fs_write32 (fs, 0)) /* nbehind */ - return 0; - if (! fs_write32 (fs, 0)) /* flags */ - return 0; - if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ - return 0; - fs->dirty = 0; - return 1; + if (! fs_write32 (fs, FSMAGIC1)) /* magic word */ + return 0; + if (! fs_write32 (fs, fs->isize)) /* size in blocks of I list */ + return 0; + if (! fs_write32 (fs, fs->fsize)) /* size in blocks of entire volume */ + return 0; + if (! fs_write32 (fs, fs->swapsz)) /* size in blocks of swap area */ + return 0; + if (! fs_write32 (fs, fs->nfree)) /* number of in core free blocks */ + return 0; + for (i=0; ifree[i])) + return 0; + } + if (! fs_write32 (fs, fs->ninode)) /* number of in core I nodes */ + return 0; + for (i=0; iinode[i])) + return 0; + } + if (! fs_write32 (fs, fs->flock)) + return 0; + if (! fs_write32 (fs, fs->fmod)) + return 0; + if (! fs_write32 (fs, fs->ilock)) + return 0; + if (! fs_write32 (fs, fs->ronly)) + return 0; + if (! fs_write32 (fs, fs->utime)) /* current date of last update */ + return 0; + if (! fs_write32 (fs, fs->tfree)) /* total free blocks */ + return 0; + if (! fs_write32 (fs, fs->tinode)) /* total free inodes */ + return 0; + if (! fs_write (fs, (unsigned char*) fs->fsmnt, MAXMNTLEN)) + return 0; /* ordinary file mounted on */ + if (! fs_write32 (fs, 0)) /* lasti*/ + return 0; + if (! fs_write32 (fs, 0)) /* nbehind */ + return 0; + if (! fs_write32 (fs, 0)) /* flags */ + return 0; + if (! fs_write32 (fs, FSMAGIC2)) /* magic word */ + return 0; + fs->dirty = 0; + return 1; } void fs_print (fs_t *fs, FILE *out) { - int i; + int i; - fprintf (out, " File: %s\n", fs->filename); - fprintf (out, " Volume size: %u blocks\n", fs->fsize); - fprintf (out, " Inode list size: %u blocks\n", fs->isize); - fprintf (out, " Swap size: %u blocks\n", fs->swapsz); - fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); - fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); - fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, - fs->fsmnt[0] ? fs->fsmnt : "(none)"); - fprintf (out, " In-core free list: %u blocks", fs->nfree); - if (verbose) - for (i=0; i < NICFREE && i < fs->nfree; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->free[i]); - } - fprintf (out, "\n"); + fprintf (out, " File: %s\n", fs->filename); + fprintf (out, " Volume size: %u blocks\n", fs->fsize); + fprintf (out, " Inode list size: %u blocks\n", fs->isize); + fprintf (out, " Swap size: %u blocks\n", fs->swapsz); + fprintf (out, " Total free blocks: %u blocks\n", fs->tfree); + fprintf (out, " Total free inodes: %u inodes\n", fs->tinode); + fprintf (out, " Last mounted on: %.*s\n", MAXMNTLEN, + fs->fsmnt[0] ? fs->fsmnt : "(none)"); + fprintf (out, " In-core free list: %u blocks", fs->nfree); + if (verbose) { + for (i=0; i < NICFREE && i < fs->nfree; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->free[i]); + } + } + fprintf (out, "\n"); - fprintf (out, " In-core free inodes: %u inodes", fs->ninode); - if (verbose) - for (i=0; i < NICINOD && i < fs->ninode; ++i) { - if (i % 10 == 0) - fprintf (out, "\n "); - fprintf (out, " %u", fs->inode[i]); - } - fprintf (out, "\n"); - if (verbose) { -// fprintf (out, " Free list lock: %u\n", fs->flock); -// fprintf (out, " Inode list lock: %u\n", fs->ilock); -// fprintf (out, "Super block modified: %u\n", fs->fmod); -// fprintf (out, " Mounted read-only: %u\n", fs->ronly); -// fprintf (out, " Circ.search start: %u\n", fs->lasti); -// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); -// fprintf (out, " Mount flags: 0x%x\n", fs->flags); - } + fprintf (out, " In-core free inodes: %u inodes", fs->ninode); + if (verbose) { + for (i=0; i < NICINOD && i < fs->ninode; ++i) { + if (i % 10 == 0) + fprintf (out, "\n "); + fprintf (out, " %u", fs->inode[i]); + } + } + fprintf (out, "\n"); + if (verbose) { +// fprintf (out, " Free list lock: %u\n", fs->flock); +// fprintf (out, " Inode list lock: %u\n", fs->ilock); +// fprintf (out, "Super block modified: %u\n", fs->fmod); +// fprintf (out, " Mounted read-only: %u\n", fs->ronly); +// fprintf (out, " Circ.search start: %u\n", fs->lasti); +// fprintf (out, " Circ.search behind: %u\n", fs->nbehind); +// fprintf (out, " Mount flags: 0x%x\n", fs->flags); + } - fprintf (out, " Last update time: %s", ctime (&fs->utime)); + fprintf (out, " Last update time: %s", ctime (&fs->utime)); } void fs_close (fs_t *fs) { - if (fs->fd < 0) - return; + if (fs->fd < 0) + return; - close (fs->fd); - fs->fd = -1; + close (fs->fd); + fs->fd = -1; } From b44cab756f14d00fe172e27a93cc37835116312a Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 31 Jul 2014 20:55:42 -0700 Subject: [PATCH 32/40] Fsutil: new option --scan to create manifest from directory contents. --- tools/fsutil/Makefile | 5 +- tools/fsutil/fsutil.c | 160 +++++++++++++++++++++++++++++++++++++- tools/fsutil/manifest.txt | 30 +++++++ 3 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 tools/fsutil/manifest.txt diff --git a/tools/fsutil/Makefile b/tools/fsutil/Makefile index 476e890..cb39a8e 100644 --- a/tools/fsutil/Makefile +++ b/tools/fsutil/Makefile @@ -8,7 +8,7 @@ PROG = fsutil #LIBS = -largp # Fuse -CFLAGS += $(shell pkg-config fuse --cflags) +MOUNT_CFLAGS = $(shell pkg-config fuse --cflags) LIBS += $(shell pkg-config fuse --libs) all: $(PROG) @@ -29,6 +29,9 @@ root.bin: $(PROG) swap.bin: dd bs=1k count=2048 < /dev/zero > $@ +mount.o: mount.c bsdfs.h + $(CC) $(CFLAGS) $(MOUNT_CFLAGS) -c -o $@ $< + block.o: block.c bsdfs.h check.o: check.c bsdfs.h create.o: create.c bsdfs.h diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 627b366..135592f 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "bsdfs.h" int verbose; @@ -39,6 +40,7 @@ int newfs; int check; int fix; int mount; +int scan; unsigned kbytes; unsigned swap_kbytes; @@ -57,6 +59,7 @@ static struct option program_options[] = { { "check", no_argument, 0, 'c' }, { "fix", no_argument, 0, 'f' }, { "mount", no_argument, 0, 'm' }, + { "scan", no_argument, 0, 'S' }, { "new", required_argument, 0, 'n' }, { "swap", required_argument, 0, 's' }, { "manifest", required_argument, 0, 'M' }, @@ -80,6 +83,7 @@ static void print_help (char *progname) printf (" %s --check [--fix] filesys.img\n", progname); printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); printf (" %s --mount filesys.img dir\n", progname); + printf (" %s --scan dir > file\n", progname); printf ("\n"); printf ("Options:\n"); printf (" -a, --add Add files to filesystem.\n"); @@ -91,6 +95,7 @@ static void print_help (char *progname) printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); printf (" -M file, --manifest=file List of files and attributes to create.\n"); printf (" -m, --mount Mount the filesystem.\n"); + printf (" -S, --scan Create a manifest from directory contents.\n"); printf (" -v, --verbose Be verbose.\n"); printf (" -V, --version Print version information and then exit.\n"); printf (" -h, --help Print this message.\n"); @@ -429,6 +434,148 @@ void add_contents (fs_t *fs, const char *dirname, const char *manifest) printf ("TODO: use manifest '%s'\n", manifest); } +/* + * Compare two entries of file traverse scan. + */ +static int ftsent_compare (const FTSENT **a, const FTSENT **b) +{ + return strcmp((*a)->fts_name, (*b)->fts_name); +} + +/* + * Store information about the link: dev, inode and path. + */ +typedef struct _link_info_t link_info_t; +struct _link_info_t { + link_info_t *next; + dev_t dev; + ino_t ino; + char path[1]; +}; + +static link_info_t *link_list; + +static void add_link (dev_t dev, ino_t ino, char *path) +{ + link_info_t *info; + + info = (link_info_t*) malloc (strlen (path) + sizeof (link_info_t)); + if (! info) { + fprintf (stderr, "%s: no memory for link info\n", path); + return; + } + info->dev = dev; + info->ino = ino; + strcpy (info->path, path); + + /* Insert into the list. */ + info->next = link_list; + link_list = info; +} + +/* + * Store information about the link: dev, inode and path. + */ +static char *find_link (dev_t dev, ino_t ino) +{ + link_info_t *info = link_list; + + for (info=link_list; info; info=info->next) { + if (info->dev == dev && info->ino == ino) + return info->path; + } + return 0; +} + +/* + * Create a manifest from directory contents. + */ +void manifest_scan (const char *dirname) +{ + FTS *dir; + FTSENT *node; + char *argv[2], *path, *target, buf[BSDFS_BSIZE]; + struct stat st; + int prefix_len, mode, len; + + argv[0] = (char*) dirname; + argv[1] = 0; + dir = fts_open (argv, FTS_PHYSICAL | FTS_NOCHDIR, &ftsent_compare); + if (! dir) { + fprintf (stderr, "%s: cannot open\n", dirname); + return; + } + prefix_len = strlen (dirname); + + printf ("# Manifest for directory %s\n", dirname); + for (;;) { + node = fts_read(dir); + if (! node) + break; + + path = node->fts_path + prefix_len; + if (path[0] == 0) + continue; + + st = *node->fts_statp; + mode = st.st_mode & 07777; + + switch (node->fts_info) { + case FTS_D: + /* Directory. */ + printf ("\ndir %s\n", path); + break; + + case FTS_F: + /* Regular file. */ + if (st.st_nlink > 1) { + /* Hard link to file. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + printf ("\nlink %s\n", path); + printf ("target %s\n", target); + continue; + } + add_link (st.st_dev, st.st_ino, path); + } + printf ("\nfile %s\n", path); + break; + + case FTS_SL: + /* Symlink. */ + if (st.st_nlink > 1) { + /* Hard link to symlink. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + printf ("\nlink %s\n", path); + printf ("target %s\n", target); + continue; + } + add_link (st.st_dev, st.st_ino, path); + } + printf ("\nsymlink %s\n", path); + + /* Get the target of symlink. */ + len = readlink(node->fts_accpath, buf, sizeof(buf) - 1); + if (len < 0) { + fprintf (stderr, "%s: cannot read\n", node->fts_accpath); + continue; + } + buf[len] = 0; + printf ("target %s\n", buf); + break; + + default: + /* Ignore all other variants. */ + continue; + } + printf ("mode %o\n", mode); + printf ("owner %u\n", st.st_uid); + printf ("group %u\n", st.st_gid); + } + fts_close (dir); +} + int main (int argc, char **argv) { int i, key; @@ -437,7 +584,7 @@ int main (int argc, char **argv) const char *manifest = 0; for (;;) { - key = getopt_long (argc, argv, "vaxmMn:cfs:", + key = getopt_long (argc, argv, "vaxmMSn:cfs:", program_options, 0); if (key == -1) break; @@ -464,6 +611,9 @@ int main (int argc, char **argv) case 'm': ++mount; break; + case 'S': + ++scan; + break; case 's': swap_kbytes = strtol (optarg, 0, 0); break; @@ -486,7 +636,7 @@ int main (int argc, char **argv) (add && i >= argc) || (newfs && i != argc-1 && i != argc-2) || (mount && i != argc-2) || - (extract + newfs + check + add + mount > 1) || + (extract + newfs + check + add + mount + scan > 1) || (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) { print_help (argv[0]); @@ -521,6 +671,12 @@ int main (int argc, char **argv) return 0; } + if (scan) { + /* Create a manifest from directory contents. */ + manifest_scan (argv[i]); + return 0; + } + /* Add or extract or info. */ if (! fs_open (&fs, argv[i], (add + mount != 0))) { fprintf (stderr, "%s: cannot open\n", argv[i]); diff --git a/tools/fsutil/manifest.txt b/tools/fsutil/manifest.txt new file mode 100644 index 0000000..6614e7d --- /dev/null +++ b/tools/fsutil/manifest.txt @@ -0,0 +1,30 @@ +# +# Skeleton of manifest file. +# +default +owner 0 +group 0 +dirmode 775 +filemode 664 +ctime now +mtime now +atime now + +dir /tmp + +file /etc/passwd +mode 444 + +link /etc/aliases +target mail/aliases + +symlink /var/tmp +target /tmp + +cdev /dev/tty +major 5 +minor 0 + +bdev /dev/sda +major 8 +minor 0 From cb4ca7f73a32ef612591695a9fe773e14c8116c8 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 1 Aug 2014 14:29:22 -0700 Subject: [PATCH 33/40] Fsutuil: move manifest routines to a separate file. --- tools/fsutil/Makefile | 6 +- tools/fsutil/fsutil.c | 150 +----------------- tools/fsutil/manifest.c | 318 ++++++++++++++++++++++++++++++++++++++ tools/fsutil/manifest.h | 81 ++++++++++ tools/fsutil/manifest.txt | 3 - 5 files changed, 410 insertions(+), 148 deletions(-) create mode 100644 tools/fsutil/manifest.c create mode 100644 tools/fsutil/manifest.h diff --git a/tools/fsutil/Makefile b/tools/fsutil/Makefile index cb39a8e..fa1a27b 100644 --- a/tools/fsutil/Makefile +++ b/tools/fsutil/Makefile @@ -1,7 +1,8 @@ CC = gcc -g CFLAGS = -O -Wall DESTDIR = /usr/local -OBJS = fsutil.o superblock.o block.c inode.o create.o check.o file.o mount.o +OBJS = fsutil.o superblock.o block.c inode.o create.o check.o \ + file.o mount.o manifest.o PROG = fsutil # For Mac OS X @@ -36,6 +37,7 @@ block.o: block.c bsdfs.h check.o: check.c bsdfs.h create.o: create.c bsdfs.h file.o: file.c bsdfs.h -fsutil.o: fsutil.c bsdfs.h +fsutil.o: fsutil.c bsdfs.h manifest.h inode.o: inode.c bsdfs.h +manifest.o: manifest.c bsdfs.h manifest.h superblock.o: superblock.c bsdfs.h diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 135592f..a88058c 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -32,6 +32,7 @@ #include #include #include "bsdfs.h" +#include "manifest.h" int verbose; int extract; @@ -434,153 +435,12 @@ void add_contents (fs_t *fs, const char *dirname, const char *manifest) printf ("TODO: use manifest '%s'\n", manifest); } -/* - * Compare two entries of file traverse scan. - */ -static int ftsent_compare (const FTSENT **a, const FTSENT **b) -{ - return strcmp((*a)->fts_name, (*b)->fts_name); -} - -/* - * Store information about the link: dev, inode and path. - */ -typedef struct _link_info_t link_info_t; -struct _link_info_t { - link_info_t *next; - dev_t dev; - ino_t ino; - char path[1]; -}; - -static link_info_t *link_list; - -static void add_link (dev_t dev, ino_t ino, char *path) -{ - link_info_t *info; - - info = (link_info_t*) malloc (strlen (path) + sizeof (link_info_t)); - if (! info) { - fprintf (stderr, "%s: no memory for link info\n", path); - return; - } - info->dev = dev; - info->ino = ino; - strcpy (info->path, path); - - /* Insert into the list. */ - info->next = link_list; - link_list = info; -} - -/* - * Store information about the link: dev, inode and path. - */ -static char *find_link (dev_t dev, ino_t ino) -{ - link_info_t *info = link_list; - - for (info=link_list; info; info=info->next) { - if (info->dev == dev && info->ino == ino) - return info->path; - } - return 0; -} - -/* - * Create a manifest from directory contents. - */ -void manifest_scan (const char *dirname) -{ - FTS *dir; - FTSENT *node; - char *argv[2], *path, *target, buf[BSDFS_BSIZE]; - struct stat st; - int prefix_len, mode, len; - - argv[0] = (char*) dirname; - argv[1] = 0; - dir = fts_open (argv, FTS_PHYSICAL | FTS_NOCHDIR, &ftsent_compare); - if (! dir) { - fprintf (stderr, "%s: cannot open\n", dirname); - return; - } - prefix_len = strlen (dirname); - - printf ("# Manifest for directory %s\n", dirname); - for (;;) { - node = fts_read(dir); - if (! node) - break; - - path = node->fts_path + prefix_len; - if (path[0] == 0) - continue; - - st = *node->fts_statp; - mode = st.st_mode & 07777; - - switch (node->fts_info) { - case FTS_D: - /* Directory. */ - printf ("\ndir %s\n", path); - break; - - case FTS_F: - /* Regular file. */ - if (st.st_nlink > 1) { - /* Hard link to file. */ - target = find_link (st.st_dev, st.st_ino); - if (target) { - printf ("\nlink %s\n", path); - printf ("target %s\n", target); - continue; - } - add_link (st.st_dev, st.st_ino, path); - } - printf ("\nfile %s\n", path); - break; - - case FTS_SL: - /* Symlink. */ - if (st.st_nlink > 1) { - /* Hard link to symlink. */ - target = find_link (st.st_dev, st.st_ino); - if (target) { - printf ("\nlink %s\n", path); - printf ("target %s\n", target); - continue; - } - add_link (st.st_dev, st.st_ino, path); - } - printf ("\nsymlink %s\n", path); - - /* Get the target of symlink. */ - len = readlink(node->fts_accpath, buf, sizeof(buf) - 1); - if (len < 0) { - fprintf (stderr, "%s: cannot read\n", node->fts_accpath); - continue; - } - buf[len] = 0; - printf ("target %s\n", buf); - break; - - default: - /* Ignore all other variants. */ - continue; - } - printf ("mode %o\n", mode); - printf ("owner %u\n", st.st_uid); - printf ("group %u\n", st.st_gid); - } - fts_close (dir); -} - int main (int argc, char **argv) { int i, key; fs_t fs; fs_inode_t inode; + manifest_t m; const char *manifest = 0; for (;;) { @@ -673,7 +533,11 @@ int main (int argc, char **argv) if (scan) { /* Create a manifest from directory contents. */ - manifest_scan (argv[i]); + if (! manifest_scan (&m, argv[i])) { + fprintf (stderr, "%s: cannot read\n", argv[i]); + return -1; + } + manifest_print (&m); return 0; } diff --git a/tools/fsutil/manifest.c b/tools/fsutil/manifest.c new file mode 100644 index 0000000..5a6d517 --- /dev/null +++ b/tools/fsutil/manifest.c @@ -0,0 +1,318 @@ +/* + * Routines to handle manifest files. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include +#include +#include +#include +#include +#include "bsdfs.h" +#include "manifest.h" + +/* + * Manifest entry. + */ +struct _entry_t { + entry_t *next; + int type; /* d, f, l, s, b or c */ + int mode; + int owner; + int group; + int major; + int minor; + char *link; /* Target for link or symlink */ + char path[1]; +}; + +/* + * Linked list of information for finding hard links. + */ +typedef struct _link_info_t link_info_t; +struct _link_info_t { + link_info_t *next; + dev_t dev; + ino_t ino; + char path[1]; +}; + +static link_info_t *link_list; /* List of hard links. */ + +/* + * Store information about the hard link: dev, inode and path. + */ +static void keep_link (dev_t dev, ino_t ino, char *path) +{ + link_info_t *info; + + info = (link_info_t*) malloc (strlen (path) + sizeof (link_info_t)); + if (! info) { + fprintf (stderr, "%s: no memory for link info\n", path); + return; + } + info->dev = dev; + info->ino = ino; + strcpy (info->path, path); + + /* Insert into the list. */ + info->next = link_list; + link_list = info; +} + +/* + * Find a hard link by dev and inode number. + * Return a path. + */ +static char *find_link (dev_t dev, ino_t ino) +{ + link_info_t *info = link_list; + + for (info=link_list; info; info=info->next) { + if (info->dev == dev && info->ino == ino) + return info->path; + } + return 0; +} + +/* + * Add new entry to the manifest. + */ +static void add_entry (manifest_t *m, int filetype, + char *path, char *link, int mode, int owner, int group) +{ + entry_t *e; + + e = malloc (sizeof(entry_t) + strlen (path)); + if (! e) { + fprintf (stderr, "%s: no memory for entry\n", path); + return; + } + + e->next = 0; + e->type = filetype; + e->mode = mode; + e->owner = owner; + e->group = group; + e->major = 0; + e->minor = 0; + e->link = 0; + e->link = link ? strdup (link) : 0; + strcpy (e->path, path); + + /* Append to the tail of the list. */ + if (m->first == 0) { + m->first = e; + } else { + m->last->next = e; + } + m->last = e; +} + +/* + * Compare two entries of file traverse scan. + */ +static int ftsent_compare (const FTSENT **a, const FTSENT **b) +{ + return strcmp((*a)->fts_name, (*b)->fts_name); +} + +/* + * Scan the directory and create a manifest from it's contents. + * Return 0 on error. + */ +int manifest_scan (manifest_t *m, const char *dirname) +{ + FTS *dir; + FTSENT *node; + char *argv[2], *path, *target, buf[BSDFS_BSIZE]; + struct stat st; + int prefix_len, mode, len; + + /* Clear manifest header. */ + m->first = 0; + m->last = 0; + m->filemode = 0; + m->dirmode = 0; + m->owner = 0; + m->group = 0; + + /* Open directory. */ + argv[0] = (char*) dirname; + argv[1] = 0; + dir = fts_open (argv, FTS_PHYSICAL | FTS_NOCHDIR, &ftsent_compare); + if (! dir) { + fprintf (stderr, "%s: cannot open\n", dirname); + return 0; + } + prefix_len = strlen (dirname); + + printf ("# Manifest for directory %s\n", dirname); + for (;;) { + /* Read next directory entry. */ + node = fts_read(dir); + if (! node) + break; + + path = node->fts_path + prefix_len; + if (path[0] == 0) + continue; + + st = *node->fts_statp; + mode = st.st_mode & 07777; + + switch (node->fts_info) { + case FTS_D: + /* Directory. */ + add_entry (m, 'd', path, 0, mode, st.st_uid, st.st_gid); + break; + + case FTS_F: + /* Regular file. */ + if (st.st_nlink > 1) { + /* Hard link to file. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid); + break; + } + keep_link (st.st_dev, st.st_ino, path); + } + add_entry (m, 'f', path, 0, mode, st.st_uid, st.st_gid); + break; + + case FTS_SL: + /* Symlink. */ + if (st.st_nlink > 1) { + /* Hard link to symlink. */ + target = find_link (st.st_dev, st.st_ino); + if (target) { + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid); + break; + } + keep_link (st.st_dev, st.st_ino, path); + } + /* Get the target of symlink. */ + len = readlink (node->fts_accpath, buf, sizeof(buf) - 1); + if (len < 0) { + fprintf (stderr, "%s: cannot read\n", node->fts_accpath); + break; + } + buf[len] = 0; + add_entry (m, 's', path, buf, mode, st.st_uid, st.st_gid); + break; + + default: + /* Ignore all other variants. */ + break; + } + } + fts_close (dir); + return 1; +} + +/* + * Dump the manifest to a text file. + */ +void manifest_print (manifest_t *m) +{ + void *cursor = 0; + char *path, *link; + int filetype, mode, owner, group, major, minor; + + cursor = 0; + while ((filetype = manifest_iterate (m, &cursor, &path, &link, &mode, + &owner, &group, &major, &minor)) != 0) + { + switch (filetype) { + case 'd': + /* Directory. */ + printf ("\ndir %s\n", path); + break; + case 'f': + /* Regular file. */ + printf ("\nfile %s\n", path); + break; + case 'l': + /* Hard link to file. */ + printf ("\nlink %s\n", path); + printf ("target %s\n", link); + continue; + case 's': + /* Symlink. */ + printf ("\nsymlink %s\n", path); + printf ("target %s\n", link); + break; + case 'b': + /* Block device. */ + printf ("\nbdev %s\n", path); + printf ("major %u\n", major); + printf ("minor %u\n", minor); + break; + case 'c': + /* Character device. */ + printf ("\ncdev %s\n", path); + printf ("major %u\n", major); + printf ("minor %u\n", minor); + break; + default: + /* Ignore all other variants. */ + continue; + } + printf ("mode %o\n", mode); + printf ("owner %u\n", owner); + printf ("group %u\n", group); + } +} + +/* + * Load a manifest from the text file. + * Return 0 on error. + */ +int manifest_load (manifest_t *m, const char *filename) +{ + //TODO + return 0; +} + +/* + * Iterate through the manifest. + */ +int manifest_iterate (manifest_t *m, void **last, char **path, char **link, + int *mode, int *owner, int *group, int *major, int *minor) +{ + /* Get the next entry. */ + entry_t *e = *last ? ((entry_t*)*last)->next : m->first; + + if (! e) + return 0; + + /* Fetch information about this entry. */ + *last = (void*) e; /* Pointer to a last processed entry. */ + *path = e->path; + *link = e->link; + *mode = (e->mode != -1) ? e->mode : (e->type == 'd') ? m->dirmode : m->filemode; + *owner = (e->owner != -1) ? e->owner : m->owner; + *group = (e->group != -1) ? e->group : m->group; + *major = e->major; + *minor = e->minor; + return e->type; +} diff --git a/tools/fsutil/manifest.h b/tools/fsutil/manifest.h new file mode 100644 index 0000000..063c0bd --- /dev/null +++ b/tools/fsutil/manifest.h @@ -0,0 +1,81 @@ +/* + * Routines to handle manifest files. + * + * Copyright (C) 2014 Serge Vakulenko, + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ + +/* + * Manifest header holds a linked list of file entries. + */ +typedef struct _manifest_t manifest_t; +typedef struct _entry_t entry_t; +struct _manifest_t { + entry_t *first; + entry_t *last; + int filemode; /* Default mode for files */ + int dirmode; /* Default mode for directories */ + int owner; /* Default owner */ + int group; /* Default group */ +}; + +/* + * Manifest entry. + */ + +/* + * Scan the directory and create a manifest from it's contents. + * Return 0 on error. + */ +int manifest_scan (manifest_t *m, const char *dirname); + +/* + * Load a manifest from the text file. + * Return 0 on error. + */ +int manifest_load (manifest_t *m, const char *filename); + +/* + * Dump the manifest to a text file. + */ +void manifest_print (manifest_t *m); + +/* + * Iterate through the manifest. + * Example: + * void *cursor = 0; + * char *path, *link; + * int filetype, mode, owner, group, major, minor; + * + * while ((filetype = manifest_iterate (m, &cursor, &path, &link, + * &mode, &owner, &group, &major, &minor)) != 0) + * { + * switch (filetype) { + * case 'd': // directory + * case 'f': // regular file + * case 'l': // hard link + * case 's': // symlink + * case 'b': // block device + * case 'c': // char device + * } + * } + */ +int manifest_iterate (manifest_t *m, void **cursor, char **path, char **link, + int *mode, int *owner, int *group, int *major, int *minor); diff --git a/tools/fsutil/manifest.txt b/tools/fsutil/manifest.txt index 6614e7d..5f29cac 100644 --- a/tools/fsutil/manifest.txt +++ b/tools/fsutil/manifest.txt @@ -6,9 +6,6 @@ owner 0 group 0 dirmode 775 filemode 664 -ctime now -mtime now -atime now dir /tmp From 8f4aad27f9041bf2864cc82b6873d4d79e71ab3d Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 1 Aug 2014 17:49:59 -0700 Subject: [PATCH 34/40] Fsutil: able to create filesystem contents from manifest. --- Makefile | 24 ++-- tools/fsutil/fsutil.c | 240 +++++++++++++++++++++++++++++++--------- tools/fsutil/manifest.c | 2 +- 3 files changed, 196 insertions(+), 70 deletions(-) diff --git a/Makefile b/Makefile index 030221d..f697606 100644 --- a/Makefile +++ b/Makefile @@ -27,9 +27,9 @@ DUINOMITEEUART = sys/pic32/duinomite-e-uart/DUINOMITE-E-UART PINGUINO = sys/pic32/pinguino-micro/PINGUINO-MICRO DIP = sys/pic32/dip/DIP BAREMETAL = sys/pic32/baremetal/BAREMETAL -RETROONE = sys/pic32/retroone/RETROONE -FUBARINO = sys/pic32/fubarino/FUBARINO -FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC +RETROONE = sys/pic32/retroone/RETROONE +FUBARINO = sys/pic32/fubarino/FUBARINO +FUBARINOBIG = sys/pic32/fubarino/FUBARINO-UART2CONS-UART1-SRAMC MMBMX7 = sys/pic32/mmb-mx7/MMB-MX7 # Select target board @@ -100,19 +100,15 @@ BDEVS = dev/rd0!b0:0 dev/rd0a!b0:1 dev/rd0b!b0:2 dev/rd0c!b0:3 dev/rd0 BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4 BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4 BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4 -BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2 +BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2 -D_CONSOLE = dev/console!c0:0 -D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3 -D_TTY = dev/tty!c2:0 -D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2 -D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2 +D_CONSOLE = dev/console!c0:0 +D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3 +D_TTY = dev/tty!c2:0 +D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2 +D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2 -U_DIRS = $(addsuffix /,$(shell find u -type d ! -path '*/.svn*')) -U_FILES = $(shell find u -type f ! -path '*/.svn/*') -#U_ALL = $(patsubst u/%,%,$(U_DIRS) $(U_FILES)) - -CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP) +CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP) all: tools build kernel $(MAKE) fs diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index a88058c..05bc81a 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -79,16 +79,14 @@ static void print_help (char *progname) printf ("\n"); printf ("Usage:\n"); printf (" %s [--verbose] filesys.img\n", progname); - printf (" %s --add filesys.img files...\n", progname); - printf (" %s --extract filesys.img\n", progname); printf (" %s --check [--fix] filesys.img\n", progname); printf (" %s --new=kbytes [--swap=kbytes] [--manifest=file] filesys.img [dir]\n", progname); printf (" %s --mount filesys.img dir\n", progname); + printf (" %s --add filesys.img files...\n", progname); + printf (" %s --extract filesys.img\n", progname); printf (" %s --scan dir > file\n", progname); printf ("\n"); printf ("Options:\n"); - printf (" -a, --add Add files to filesystem.\n"); - printf (" -x, --extract Extract all files.\n"); printf (" -c, --check Check filesystem, use -c -f to fix.\n"); printf (" -f, --fix Fix bugs in filesystem.\n"); printf (" -n NUM, --new=NUM Create new filesystem, size in kbytes.\n"); @@ -96,6 +94,8 @@ static void print_help (char *progname) printf (" -s NUM, --swap=NUM Size of swap area in kbytes.\n"); printf (" -M file, --manifest=file List of files and attributes to create.\n"); printf (" -m, --mount Mount the filesystem.\n"); + printf (" -a, --add Add files to filesystem.\n"); + printf (" -x, --extract Extract all files.\n"); printf (" -S, --scan Create a manifest from directory contents.\n"); printf (" -v, --verbose Be verbose.\n"); printf (" -V, --version Print version information and then exit.\n"); @@ -297,7 +297,7 @@ void scanner (fs_inode_t *dir, fs_inode_t *inode, /* * Create a directory. */ -void add_directory (fs_t *fs, char *name) +void add_directory (fs_t *fs, char *name, int mode, int owner, int group) { fs_inode_t dir, parent; char buf [BSDFS_BSIZE], *p; @@ -315,7 +315,9 @@ void add_directory (fs_t *fs, char *name) } /* Create directory. */ - int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, INODE_MODE_FDIR | 0777); + mode &= 07777; + mode |= INODE_MODE_FDIR; + int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, mode); if (! done) { fprintf (stderr, "%s: directory inode create failed\n", name); return; @@ -324,7 +326,9 @@ void add_directory (fs_t *fs, char *name) /* The directory already existed. */ return; } - fs_inode_save (&dir, 0); + dir.uid = owner; + dir.gid = group; + fs_inode_save (&dir, 1); /* Make parent link '..' */ strcpy (buf, name); @@ -345,83 +349,166 @@ void add_directory (fs_t *fs, char *name) /* * Create a device node. */ -void add_device (fs_t *fs, char *name, char *spec) +void add_device (fs_t *fs, char *name, int mode, int owner, int group, + int type, int majr, int minr) { fs_inode_t dev; - int majr, minr; - char type; - if (sscanf (spec, "%c%d:%d", &type, &majr, &minr) != 3 || - (type != 'c' && type != 'b') || - majr < 0 || majr > 255 || minr < 0 || minr > 255) { - fprintf (stderr, "%s: invalid device specification\n", spec); - fprintf (stderr, "expected c: or b:\n"); - return; - } - if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, 0666 | - ((type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR))) { + mode &= 07777; + mode |= (type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR; + if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, mode)) { fprintf (stderr, "%s: device inode create failed\n", name); return; } dev.addr[1] = majr << 8 | minr; + dev.uid = owner; + dev.gid = group; time (&dev.mtime); fs_inode_save (&dev, 1); } /* - * Copy file to filesystem. - * When name is ended by slash as "name/", directory is created. + * Copy regular file to filesystem. */ -void add_file (fs_t *fs, char *name) +void add_file (fs_t *fs, const char *path, const char *dirname, + int mode, int owner, int group) { fs_file_t file; FILE *fd; + char accpath [BSDFS_BSIZE]; unsigned char data [BSDFS_BSIZE]; struct stat st; - char *p; int len; + if (dirname && *dirname) { + /* Concatenate directory name and file name. */ + strcpy (accpath, dirname); + len = strlen (accpath); + if (accpath[len-1] != '/' && path[0] != '/') + strcat (accpath, "/"); + strcat (accpath, path); + } else { + /* Use filename relative to current directory. */ + strcpy (accpath, path); + } + fd = fopen (accpath, "r"); + if (! fd) { + perror (accpath); + return; + } + fstat (fileno(fd), &st); + if (mode == -1) + mode = st.st_mode; + mode &= 07777; + mode |= INODE_MODE_FREG; + if (! fs_file_create (fs, &file, path, mode)) { + fprintf (stderr, "%s: cannot create\n", path); + return; + } + for (;;) { + len = fread (data, 1, sizeof (data), fd); +/* printf ("read %d bytes from %s\n", len, accpath);*/ + if (len < 0) + perror (accpath); + if (len <= 0) + break; + if (! fs_file_write (&file, data, len)) { + fprintf (stderr, "%s: write error\n", path); + break; + } + } + file.inode.uid = owner; + file.inode.gid = group; + file.inode.mtime = st.st_mtime; + file.inode.dirty = 1; + fs_file_close (&file); + fclose (fd); +} + +/* + * Create a symlink. + */ +void add_symlink (fs_t *fs, const char *path, const char *link, + int mode, int owner, int group) +{ + fs_file_t file; + int len; + + mode &= 07777; + mode |= INODE_MODE_FLNK; + if (! fs_file_create (fs, &file, path, mode)) { + fprintf (stderr, "%s: cannot create\n", path); + return; + } + len = strlen (link); + if (! fs_file_write (&file, (unsigned char*) link, len)) { + fprintf (stderr, "%s: write error\n", path); + return; + } + file.inode.uid = owner; + file.inode.gid = group; + time (&file.inode.mtime); + file.inode.dirty = 1; + fs_file_close (&file); +} + +/* + * Create a hard link. + */ +void add_hardlink (fs_t *fs, const char *path, const char *link) +{ + fs_inode_t source, target; + + /* Find source. */ + if (! fs_inode_by_name (fs, &source, link, INODE_OP_LOOKUP, 0)) { + fprintf (stderr, "%s: link source not found\n", link); + return; + } + if ((source.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + fprintf (stderr, "%s: cannot link directories\n", link); + return; + } + + /* Create target link. */ + if (! fs_inode_by_name (fs, &target, path, INODE_OP_LINK, source.number)) { + fprintf (stderr, "%s: link failed\n", path); + return; + } +} + +/* + * Create a file/device/directory in the filesystem. + * When name is ended by slash as "name/", directory is created. + */ +void add_object (fs_t *fs, char *name) +{ + int majr, minr; + char type; + char *p; + if (verbose) { printf ("%s\n", name); } p = strrchr (name, '/'); if (p && p[1] == 0) { *p = 0; - add_directory (fs, name); + add_directory (fs, name, 0777, 0, 0); return; } p = strrchr (name, '!'); if (p) { *p++ = 0; - add_device (fs, name, p); - return; - } - fd = fopen (name, "r"); - if (! fd) { - perror (name); - return; - } - stat (name, &st); - if (! fs_file_create (fs, &file, name, st.st_mode)) { - fprintf (stderr, "%s: cannot create\n", name); - return; - } - for (;;) { - len = fread (data, 1, sizeof (data), fd); -/* printf ("read %d bytes from %s\n", len, name);*/ - if (len < 0) - perror (name); - if (len <= 0) - break; - if (! fs_file_write (&file, data, len)) { - fprintf (stderr, "%s: write error\n", name); - break; + if (sscanf (p, "%c%d:%d", &type, &majr, &minr) != 3 || + (type != 'c' && type != 'b') || + majr < 0 || majr > 255 || minr < 0 || minr > 255) { + fprintf (stderr, "%s: invalid device specification\n", p); + fprintf (stderr, "expected c: or b:\n"); + return; } + add_device (fs, name, 0666, 0, 0, type, majr, minr); + return; } - file.inode.mtime = st.st_mtime; - file.inode.dirty = 1; - fs_file_close (&file); - fclose (fd); + add_file (fs, name, 0, -1, 0, 0); } /* @@ -430,9 +517,52 @@ void add_file (fs_t *fs, char *name) */ void add_contents (fs_t *fs, const char *dirname, const char *manifest) { - printf ("TODO: add contents from directory '%s'\n", dirname); - if (manifest) - printf ("TODO: use manifest '%s'\n", manifest); + manifest_t m; + void *cursor; + char *path, *link; + int filetype, mode, owner, group, majr, minr; + + if (manifest) { + /* Load manifest from file. */ + if (! manifest_load (&m, manifest)) { + fprintf (stderr, "%s: cannot read\n", manifest); + return; + } + } else { + /* Create manifest from directory contents. */ + if (! manifest_scan (&m, dirname)) { + fprintf (stderr, "%s: cannot read\n", dirname); + return; + } + } + + /* For every file in the manifest, + * add it to the target filesystem. */ + cursor = 0; + while ((filetype = manifest_iterate (&m, &cursor, &path, &link, &mode, + &owner, &group, &majr, &minr)) != 0) + { + switch (filetype) { + case 'd': + add_directory (fs, path, mode, owner, group); + break; + case 'f': + add_file (fs, path, dirname, mode, owner, group); + break; + case 'l': + add_hardlink (fs, path, link); + break; + case 's': + add_symlink (fs, path, link, mode, owner, group); + break; + case 'b': + add_device (fs, path, mode, owner, group, 'b', majr, minr); + break; + case 'c': + add_device (fs, path, mode, owner, group, 'c', majr, minr); + break; + } + } } int main (int argc, char **argv) @@ -561,7 +691,7 @@ int main (int argc, char **argv) if (add) { /* Add files i+1..argc-1 to filesystem. */ while (++i < argc) - add_file (&fs, argv[i]); + add_object (&fs, argv[i]); fs_sync (&fs, 0); fs_close (&fs); return 0; diff --git a/tools/fsutil/manifest.c b/tools/fsutil/manifest.c index 5a6d517..a41d863 100644 --- a/tools/fsutil/manifest.c +++ b/tools/fsutil/manifest.c @@ -234,7 +234,7 @@ int manifest_scan (manifest_t *m, const char *dirname) */ void manifest_print (manifest_t *m) { - void *cursor = 0; + void *cursor; char *path, *link; int filetype, mode, owner, group, major, minor; From 1cdf42ef94567d9723f45dfdd07115a91c5872a0 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 1 Aug 2014 18:17:38 -0700 Subject: [PATCH 35/40] Fsutil: inode API simplified. --- tools/fsutil/bsdfs.h | 4 ++++ tools/fsutil/file.c | 4 ++-- tools/fsutil/fsutil.c | 12 +++++------ tools/fsutil/inode.c | 41 ++++++++++++++++++++++++++++++++++++ tools/fsutil/mount.c | 48 +++++++++++++++++++++---------------------- 5 files changed, 77 insertions(+), 32 deletions(-) diff --git a/tools/fsutil/bsdfs.h b/tools/fsutil/bsdfs.h index bd54e8b..ee11332 100644 --- a/tools/fsutil/bsdfs.h +++ b/tools/fsutil/bsdfs.h @@ -185,6 +185,10 @@ int fs_inode_write (fs_inode_t *inode, unsigned long offset, int fs_inode_alloc (fs_t *fs, fs_inode_t *inode); int fs_inode_by_name (fs_t *fs, fs_inode_t *inode, const char *name, fs_op_t op, int mode); +int fs_inode_lookup (fs_t *fs, fs_inode_t *inode, const char *name); +int fs_inode_create (fs_t *fs, fs_inode_t *inode, const char *name, int mode); +int fs_inode_delete (fs_t *fs, fs_inode_t *inode, const char *name); +int fs_inode_link (fs_t *fs, fs_inode_t *inode, const char *name, int mode); int inode_build_list (fs_t *fs); int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data); diff --git a/tools/fsutil/file.c b/tools/fsutil/file.c index 13d650c..50b4f37 100644 --- a/tools/fsutil/file.c +++ b/tools/fsutil/file.c @@ -29,7 +29,7 @@ extern int verbose; int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_CREATE, mode)) { + if (! fs_inode_create (fs, &file->inode, name, mode)) { fprintf (stderr, "%s: inode open failed\n", name); return 0; } @@ -46,7 +46,7 @@ int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode) int fs_file_open (fs_t *fs, fs_file_t *file, const char *name, int wflag) { - if (! fs_inode_by_name (fs, &file->inode, name, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &file->inode, name)) { fprintf (stderr, "%s: inode open failed\n", name); return 0; } diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 05bc81a..721b467 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -309,7 +309,7 @@ void add_directory (fs_t *fs, char *name, int mode, int owner, int group) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &parent, buf)) { fprintf (stderr, "%s: cannot open directory\n", buf); return; } @@ -317,7 +317,7 @@ void add_directory (fs_t *fs, char *name, int mode, int owner, int group) /* Create directory. */ mode &= 07777; mode |= INODE_MODE_FDIR; - int done = fs_inode_by_name (fs, &dir, name, INODE_OP_CREATE, mode); + int done = fs_inode_create (fs, &dir, name, mode); if (! done) { fprintf (stderr, "%s: directory inode create failed\n", name); return; @@ -333,7 +333,7 @@ void add_directory (fs_t *fs, char *name, int mode, int owner, int group) /* Make parent link '..' */ strcpy (buf, name); strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { + if (! fs_inode_link (fs, &dir, buf, parent.number)) { fprintf (stderr, "%s: dotdot link failed\n", name); return; } @@ -356,7 +356,7 @@ void add_device (fs_t *fs, char *name, int mode, int owner, int group, mode &= 07777; mode |= (type == 'b') ? INODE_MODE_FBLK : INODE_MODE_FCHR; - if (! fs_inode_by_name (fs, &dev, name, INODE_OP_CREATE, mode)) { + if (! fs_inode_create (fs, &dev, name, mode)) { fprintf (stderr, "%s: device inode create failed\n", name); return; } @@ -460,7 +460,7 @@ void add_hardlink (fs_t *fs, const char *path, const char *link) fs_inode_t source, target; /* Find source. */ - if (! fs_inode_by_name (fs, &source, link, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &source, link)) { fprintf (stderr, "%s: link source not found\n", link); return; } @@ -470,7 +470,7 @@ void add_hardlink (fs_t *fs, const char *path, const char *link) } /* Create target link. */ - if (! fs_inode_by_name (fs, &target, path, INODE_OP_LINK, source.number)) { + if (! fs_inode_link (fs, &target, path, source.number)) { fprintf (stderr, "%s: link failed\n", path); return; } diff --git a/tools/fsutil/inode.c b/tools/fsutil/inode.c index a07a1c5..38bdc22 100644 --- a/tools/fsutil/inode.c +++ b/tools/fsutil/inode.c @@ -851,3 +851,44 @@ int fs_inode_alloc (fs_t *fs, fs_inode_t *inode) } } } + +/* + * Find inode by name. + * Return 0 on any error. + * Return 1 when the inode was found. + */ +int fs_inode_lookup (fs_t *fs, fs_inode_t *inode, const char *name) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_LOOKUP, 0); +} + +/* + * Create inode by name. + * Return 0 on any error. + * Return 1 when the inode was found. + * Return 2 when the inode was created. + */ +int fs_inode_create (fs_t *fs, fs_inode_t *inode, const char *name, int mode) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_CREATE, mode); +} + +/* + * Delete inode by name. + * Return 0 on any error. + * Return 2 when the inode was created. + */ +int fs_inode_delete (fs_t *fs, fs_inode_t *inode, const char *name) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_DELETE, 0); +} + +/* + * Create a new link for the inode. + * Return 0 on any error. + * Return 2 when the inode was linked. + */ +int fs_inode_link (fs_t *fs, fs_inode_t *inode, const char *name, int inum) +{ + return fs_inode_by_name (fs, inode, name, INODE_OP_LINK, inum); +} diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 9e451ad..69f5a60 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -116,7 +116,7 @@ int op_getattr(const char *path, struct stat *statbuf) printlog("--- op_getattr(path=\"%s\", statbuf=%p)\n", path, statbuf); - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- search failed\n"); return -ENOENT; } @@ -307,7 +307,7 @@ int op_unlink(const char *path) printlog("--- op_unlink(path=\"%s\")\n", path); /* Get the file type. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- search failed\n"); return -ENOENT; } @@ -317,7 +317,7 @@ int op_unlink(const char *path) } /* Delete file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_DELETE, 0)) { + if (! fs_inode_delete (fs, &inode, path)) { printlog("--- delete failed\n"); return -EIO; } @@ -337,7 +337,7 @@ int op_rmdir(const char *path) printlog("--- op_rmdir(path=\"%s\")\n", path); /* Get the file type. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- search failed\n"); return -ENOENT; } @@ -357,20 +357,20 @@ int op_rmdir(const char *path) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &parent, buf)) { printlog("--- parent not found\n"); return -ENOENT; } /* Delete directory. * Need to decrease a link count first. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- directory not found\n"); return -ENOENT; } --inode.nlink; fs_inode_save (&inode, 1); - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_DELETE, 0)) { + if (! fs_inode_delete (fs, &inode, path)) { printlog("--- delete failed\n"); return -EIO; } @@ -404,7 +404,7 @@ int op_mkdir(const char *path, mode_t mode) *p = 0; else *buf = 0; - if (! fs_inode_by_name (fs, &parent, buf, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &parent, buf)) { printlog("--- parent not found\n"); return -ENOENT; } @@ -412,7 +412,7 @@ int op_mkdir(const char *path, mode_t mode) /* Create directory. */ mode &= 07777; mode |= INODE_MODE_FDIR; - int done = fs_inode_by_name (fs, &dir, path, INODE_OP_CREATE, mode); + int done = fs_inode_create (fs, &dir, path, mode); if (! done) { printlog("--- cannot create dir inode\n"); return -ENOENT; @@ -426,7 +426,7 @@ int op_mkdir(const char *path, mode_t mode) /* Make parent link '..' */ strcpy (buf, path); strcat (buf, "/.."); - if (! fs_inode_by_name (fs, &dir, buf, INODE_OP_LINK, parent.number)) { + if (! fs_inode_link (fs, &dir, buf, parent.number)) { printlog("--- dotdot link failed\n"); return -EIO; } @@ -450,7 +450,7 @@ int op_link(const char *path, const char *newpath) printlog("--- op_link(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Find source. */ - if (! fs_inode_by_name (fs, &source, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &source, path)) { printlog("--- source not found\n"); return -ENOENT; } @@ -461,7 +461,7 @@ int op_link(const char *path, const char *newpath) } /* Create target link. */ - if (! fs_inode_by_name (fs, &target, newpath, INODE_OP_LINK, source.number)) { + if (! fs_inode_link (fs, &target, newpath, source.number)) { printlog("--- link failed\n"); return -EIO; } @@ -479,7 +479,7 @@ int op_rename(const char *path, const char *newpath) printlog("--- op_rename(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Find source and increase the link count. */ - if (! fs_inode_by_name (fs, &source, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &source, path)) { printlog("--- source not found\n"); return -ENOENT; } @@ -487,13 +487,13 @@ int op_rename(const char *path, const char *newpath) fs_inode_save (&source, 1); /* Create target link. */ - if (! fs_inode_by_name (fs, &target, newpath, INODE_OP_LINK, source.number)) { + if (! fs_inode_link (fs, &target, newpath, source.number)) { printlog("--- link failed\n"); return -EIO; } /* Delete the source. */ - if (! fs_inode_by_name (fs, &source, path, INODE_OP_DELETE, 0)) { + if (! fs_inode_delete (fs, &source, path)) { printlog("--- delete failed\n"); return -EIO; } @@ -513,7 +513,7 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) path, mode, dev); /* Check if the file already exists. */ - if (fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (fs_inode_lookup (fs, &inode, path)) { printlog("--- already exists\n"); return -EEXIST; } @@ -529,7 +529,7 @@ int op_mknod(const char *path, mode_t mode, dev_t dev) return -EINVAL; /* Create the file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_CREATE, mode)) { + if (! fs_inode_create (fs, &inode, path, mode)) { printlog("--- create failed\n"); return -EIO; } @@ -557,7 +557,7 @@ int op_readlink(const char *path, char *link, size_t size) path, link, size); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- file not found\n"); return -ENOENT; } @@ -588,14 +588,14 @@ int op_symlink(const char *path, const char *newpath) printlog("--- op_symlink(path=\"%s\", newpath=\"%s\")\n", path, newpath); /* Check if the file already exists. */ - if (fs_inode_by_name (fs, &inode, newpath, INODE_OP_LOOKUP, 0)) { + if (fs_inode_lookup (fs, &inode, newpath)) { printlog("--- already exists\n"); return -EEXIST; } /* Create symlink. */ mode = 0777 | INODE_MODE_FLNK; - if (! fs_inode_by_name (fs, &inode, newpath, INODE_OP_CREATE, mode)) { + if (! fs_inode_create (fs, &inode, newpath, mode)) { printlog("--- create failed\n"); return -EIO; } @@ -626,7 +626,7 @@ int op_chmod(const char *path, mode_t mode) printlog("--- op_chmod(path=\"%s\", mode=0%03o)\n", path, mode); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- file not found\n"); return -ENOENT; } @@ -650,7 +650,7 @@ int op_chown(const char *path, uid_t uid, gid_t gid) printlog("--- op_chown(path=\"%s\", uid=%d, gid=%d)\n", path, uid, gid); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- file not found\n"); return -ENOENT; } @@ -674,7 +674,7 @@ int op_utime(const char *path, struct utimbuf *ubuf) printlog("--- op_utime(path=\"%s\", ubuf=%p)\n", path, ubuf); /* Open the file. */ - if (! fs_inode_by_name (fs, &inode, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &inode, path)) { printlog("--- file not found\n"); return -ENOENT; } @@ -759,7 +759,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset printlog("--- op_readdir(path=\"%s\", buf=%p, filler=%p, offset=%lld, fi=%p)\n", path, buf, filler, offset, fi); - if (! fs_inode_by_name (fs, &dir, path, INODE_OP_LOOKUP, 0)) { + if (! fs_inode_lookup (fs, &dir, path)) { printlog("--- cannot find path %s\n", path); return -ENOENT; } From d42bfdc7b922afc99ce72e86414cbd2bec720c44 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 1 Aug 2014 21:23:38 -0700 Subject: [PATCH 36/40] Fsutil: can read manifest files. Added a manifest for root filesystem. --- filesys.manifest | 768 ++++++++++++++++++++++++++++++++++++++ tools/fsutil/manifest.c | 233 +++++++++++- tools/fsutil/manifest.txt | 6 +- 3 files changed, 990 insertions(+), 17 deletions(-) create mode 100644 filesys.manifest diff --git a/filesys.manifest b/filesys.manifest new file mode 100644 index 0000000..6910753 --- /dev/null +++ b/filesys.manifest @@ -0,0 +1,768 @@ +# +# Manifest file for RetroBSD root filesystem. +# +default +owner 0 +group 0 +dirmode 0775 +filemode 0664 + +# +# Directories. +# +dir /bin +dir /dev +dir /etc +dir /lib +dir /libexec +dir /sbin +dir /tmp +dir /u + +# +# Character devices. +# +cdev /dev/console +major 0 +minor 0 +cdev /dev/mem +major 1 +minor 0 +cdev /dev/kmem +major 1 +minor 1 +cdev /dev/null +major 1 +minor 2 +cdev /dev/zero +major 1 +minor 3 +cdev /dev/tty +major 2 +minor 0 +cdev /dev/stdin +major 3 +minor 0 +cdev /dev/stdout +major 3 +minor 1 +cdev /dev/stderr +major 3 +minor 2 +cdev /dev/temp0 +major 4 +minor 0 +cdev /dev/temp1 +major 4 +minor 1 +cdev /dev/temp2 +major 4 +minor 2 + +# +# Block devices. +# +bdev /dev/rd0 +major 0 +minor 0 +bdev /dev/rd0a +major 0 +minor 1 +bdev /dev/rd0b +major 0 +minor 2 +bdev /dev/rd0c +major 0 +minor 3 +bdev /dev/rd0d +major 0 +minor 4 +bdev /dev/rd1 +major 1 +minor 0 +bdev /dev/rd1a +major 1 +minor 1 +bdev /dev/rd1b +major 1 +minor 2 +bdev /dev/rd1c +major 1 +minor 3 +bdev /dev/rd1d +major 1 +minor 4 +bdev /dev/rd2 +major 2 +minor 0 +bdev /dev/rd2a +major 2 +minor 1 +bdev /dev/rd2b +major 2 +minor 2 +bdev /dev/rd2c +major 2 +minor 3 +bdev /dev/rd2d +major 2 +minor 4 +bdev /dev/rd3 +major 3 +minor 0 +bdev /dev/rd3a +major 3 +minor 1 +bdev /dev/rd3b +major 3 +minor 2 +bdev /dev/rd3c +major 3 +minor 3 +bdev /dev/rd3d +major 3 +minor 4 +bdev /dev/swap +major 4 +minor 64 +bdev /dev/swap0 +major 4 +minor 0 +bdev /dev/swap1 +major 4 +minor 1 +bdev /dev/swap2 +major 4 +minor 2 + +# +# Files: / +# +file /.profile + +# +# Files: /etc +# +file /etc/fstab +file /etc/gettytab +file /etc/group +file /etc/MAKEDEV +mode 0775 +file /etc/motd +file /etc/passwd +file /etc/phones +file /etc/rc +mode 0775 +file /etc/rc.local +mode 0775 +file /etc/remote +file /etc/shadow +file /etc/shells +file /etc/termcap +mode 0444 +file /etc/ttys + +# +# Files: /bin +# +default +filemode 0775 +file /bin/adb +file /bin/adc-demo +file /bin/aout +file /bin/apropos +file /bin/ar +file /bin/as +file /bin/awk +file /bin/basename +file /bin/basic +file /bin/bc +file /bin/cal +file /bin/cat +file /bin/cb +file /bin/cc +file /bin/chat-server +file /bin/chflags +file /bin/chgrp +file /bin/chmod +file /bin/chpass +mode 04755 +file /bin/cmp +file /bin/col +file /bin/comm +file /bin/compress +file /bin/cp +file /bin/cpp +file /bin/crontab +file /bin/date +file /bin/dc +file /bin/dd +file /bin/df +mode 02755 +file /bin/diff +file /bin/du +file /bin/echo +file /bin/ed +file /bin/egrep +file /bin/emg +file /bin/env +file /bin/expr +file /bin/false +file /bin/fgrep +file /bin/file +file /bin/find +file /bin/forth +file /bin/fstat +mode 02755 +file /bin/glcdtest +file /bin/globdump +file /bin/globread +file /bin/globwrite +file /bin/grep +file /bin/groups +file /bin/head +file /bin/hostid +file /bin/hostname +file /bin/id +file /bin/iostat +mode 02755 +file /bin/join +file /bin/kill +file /bin/la +file /bin/last +file /bin/lcc +file /bin/lcpp +file /bin/ld +file /bin/ln +file /bin/login +mode 04755 +file /bin/lol +file /bin/ls +file /bin/mail +mode 04755 +file /bin/make +file /bin/man +file /bin/med +file /bin/mesg +file /bin/mkdir +file /bin/more +file /bin/msec +file /bin/mv +file /bin/nice +file /bin/nm +file /bin/nohup +file /bin/ntpdate +file /bin/od +file /bin/pagesize +file /bin/passwd +mode 04755 +file /bin/picoc +file /bin/portio +file /bin/pr +file /bin/printenv +file /bin/printf +file /bin/ps +mode 02755 +file /bin/pwd +file /bin/pwm +file /bin/ranlib +file /bin/re +file /bin/renice +file /bin/renumber +file /bin/retroforth +file /bin/rev +file /bin/rm +file /bin/rmail +file /bin/rmdir +file /bin/rz +file /bin/scc +file /bin/scm +file /bin/sed +file /bin/setty +file /bin/sh +file /bin/size +file /bin/sl +file /bin/sleep +file /bin/smux +file /bin/sort +file /bin/split +file /bin/strip +file /bin/stty +file /bin/su +mode 04755 +file /bin/sum +file /bin/sync +file /bin/sysctl +file /bin/sz +file /bin/tail +file /bin/tar +file /bin/tee +file /bin/telnet +file /bin/test +file /bin/time +file /bin/tip +file /bin/touch +file /bin/tr +file /bin/true +file /bin/tsort +file /bin/tty +file /bin/uname +file /bin/uncompress +file /bin/uniq +file /bin/uucico +file /bin/uuclean +file /bin/uucp +file /bin/uudecode +file /bin/uuencode +file /bin/uulog +file /bin/uuname +file /bin/uupoll +file /bin/uuq +file /bin/uusend +file /bin/uusnap +file /bin/uux +file /bin/uuxqt +file /bin/vi +file /bin/vmstat +mode 02755 +file /bin/w +file /bin/wall +mode 02755 +file /bin/wc +file /bin/web-client +file /bin/web-server +file /bin/whereis +file /bin/who +file /bin/whoami +file /bin/write +mode 02755 +file /bin/xargs +file /bin/zcat + +link /bin/[ +target /bin/test + +link /bin/whatis +target /bin/apropos + +link /bin/chfn +target /bin/chpass +link /bin/chsh +target /bin/chpass + +file /bin/rb +target /bin/rz +file /bin/rx +target /bin/rz + +file /bin/sb +target /bin/sz +file /bin/sx +target /bin/sz + +# +# Files: /sbin +# +file /sbin/chown +file /sbin/chroot +mode 04755 +file /sbin/cron +file /sbin/devupdate +file /sbin/disktool +file /sbin/fdisk +file /sbin/fsck +file /sbin/init +mode 0700 +file /sbin/mkfs +file /sbin/mknod +file /sbin/mkpasswd +file /sbin/mount +file /sbin/pstat +mode 02755 +file /sbin/rdprof +file /sbin/reboot +file /sbin/shutdown +mode 04750 +file /sbin/talloc +file /sbin/umount +file /sbin/update +file /sbin/updatedb +file /sbin/vipw + +link /sbin/bootloader +target /sbin/reboot +link /sbin/fastboot +target /sbin/reboot +link /sbin/halt +target /sbin/reboot +link /sbin/poweroff +target /sbin/reboot + +# +# Files: /games +# +default +filemode 0775 +dir /games +file /games/adventure +file /games/arithmetic +file /games/backgammon +file /games/banner +file /games/battlestar +file /games/bcd +file /games/canfield +file /games/cfscores +file /games/factor +file /games/fish +file /games/morse +file /games/number +file /games/ppt +file /games/primes +file /games/rain +file /games/rogue +file /games/sail +file /games/teachgammon +file /games/trek +file /games/worm +file /games/worms +file /games/wump + +# +# Files: /games/lib +# +dir /games/lib +file /games/lib/adventure.dat +mode 0444 +file /games/lib/battle_strings +mode 0444 +file /games/lib/cfscores +mode 0666 + +# +# Files: /include +# +default +filemode 0664 +dir /include +dir /include/arpa +dir /include/machine +dir /include/smallc +dir /include/smallc/sys +dir /include/sys +file /include/alloca.h +file /include/a.out.h +file /include/ar.h +file /include/arpa/inet.h +file /include/assert.h +file /include/ctype.h +file /include/curses.h +file /include/dbm.h +file /include/fcntl.h +file /include/float.h +file /include/fstab.h +file /include/grp.h +file /include/kmem.h +file /include/lastlog.h +file /include/limits.h +file /include/machine/cpu.h +file /include/machine/elf_machdep.h +file /include/machine/float.h +file /include/machine/io.h +file /include/machine/limits.h +file /include/machine/machparam.h +file /include/machine/pic32mx.h +file /include/machine/rd_sdramp_config.h +file /include/machine/sdram.h +file /include/machine/ssd1926.h +file /include/machine/usb_ch9.h +file /include/machine/usb_device.h +file /include/machine/usb_function_cdc.h +file /include/machine/usb_function_hid.h +file /include/machine/usb_hal_pic32.h +file /include/math.h +file /include/mtab.h +file /include/ndbm.h +file /include/nlist.h +file /include/paths.h +file /include/pcc.h +file /include/psout.h +file /include/pwd.h +file /include/ranlib.h +file /include/regexp.h +file /include/setjmp.h +file /include/sgtty.h +file /include/smallc/curses.h +file /include/smallc/fcntl.h +file /include/smallc/signal.h +file /include/smallc/stdio.h +file /include/smallc/sys/gpio.h +file /include/smallc/sys/spi.h +file /include/smallc/wiznet.h +file /include/stab.h +file /include/stdarg.h +file /include/stddef.h +file /include/stdint.h +file /include/stdio.h +file /include/stdlib.h +file /include/string.h +file /include/strings.h +file /include/struct.h +file /include/sys/adc.h +file /include/sys/buf.h +file /include/syscall.h +file /include/sys/callout.h +file /include/sys/clist.h +file /include/sys/conf.h +file /include/sys/debug.h +file /include/sys/dir.h +file /include/sys/disk.h +file /include/sys/dkbad.h +file /include/sys/dk.h +file /include/sys/errno.h +file /include/sys/exec_aout.h +file /include/sys/exec_elf.h +file /include/sys/exec.h +file /include/sysexits.h +file /include/sys/fcntl.h +file /include/sys/file.h +file /include/sys/fs.h +file /include/sys/glcd.h +file /include/sys/glob.h +file /include/sys/gpio.h +file /include/sys/inode.h +file /include/sys/ioctl.h +file /include/sys/kernel.h +file /include/sys/map.h +file /include/sys/mount.h +file /include/sys/msgbuf.h +file /include/sys/mtio.h +file /include/sys/namei.h +file /include/sys/oc.h +file /include/sys/param.h +file /include/sys/picga.h +file /include/sys/proc.h +file /include/sys/ptrace.h +file /include/sys/pty.h +file /include/sys/rd_flash.h +file /include/sys/rdisk.h +file /include/sys/rd_mrams.h +file /include/sys/rd_sdramp.h +file /include/sys/rd_sramc.h +file /include/sys/reboot.h +file /include/sys/resource.h +file /include/sys/select.h +file /include/sys/signal.h +file /include/sys/signalvar.h +file /include/sys/spi_bus.h +file /include/sys/spi.h +file /include/sys/stat.h +file /include/sys/swap.h +file /include/sys/sysctl.h +file /include/sys/syslog.h +file /include/sys/systm.h +file /include/sys/time.h +file /include/sys/times.h +file /include/sys/trace.h +file /include/sys/ttychars.h +file /include/sys/ttydev.h +file /include/sys/tty.h +file /include/sys/types.h +file /include/sys/uart.h +file /include/sys/uio.h +file /include/sys/usb_uart.h +file /include/sys/user.h +file /include/sys/utsname.h +file /include/sys/vm.h +file /include/sys/vmmac.h +file /include/sys/vmmeter.h +file /include/sys/vmparam.h +file /include/sys/vmsystm.h +file /include/sys/wait.h +file /include/term.h +file /include/termios-todo.h +file /include/time.h +file /include/ttyent.h +file /include/tzfile.h +file /include/unistd.h +file /include/utmp.h +file /include/vmf.h + +symlink /include/errno.h +target sys/errno.h + +symlink /include/signal.h +target sys/signal.h + +symlink /include/syslog.h +target sys/syslog.h + +# +# Files: /lib +# +file /lib/crt0.o +file /lib/libc.a +file /lib/libcurses.a +file /lib/libtermlib.a +file /lib/libwiznet.a +file /lib/retroImage + +# +# Files: /libexec +# +default +filemode 0775 +file /libexec/bigram +file /libexec/code +file /libexec/diffh +file /libexec/getty +file /libexec/smallc +file /libexec/smlrc + +# +# Files: /share +# +default +filemode 0444 +dir /share +dir /share/misc +file /share/emg.keys +file /share/re.help + +# +# Files: /share/example +# +default +filemode 0664 +dir /share/example +file /share/example/ashello.S +file /share/example/blkjack.bas +file /share/example/chello.c +file /share/example/echo.S +file /share/example/fact.fth +file /share/example/hilow.bas +file /share/example/Makefile +file /share/example/prime.scm +file /share/example/skeleton.c +file /share/example/stars.bas +file /share/example/stdarg.c + +# +# Files: /share/smallc +# +dir /share/smallc +file /share/smallc/adc.c +file /share/smallc/gpio.c +file /share/smallc/hello.c +file /share/smallc/Makefile +file /share/smallc/primelist.c +file /share/smallc/primesum.c +file /share/smallc/q8.c +file /share/smallc/rain.c +file /share/smallc/test1.c +file /share/smallc/test2.c +file /share/smallc/test3.c +file /share/smallc/webserver.c + +# +# Files: /var +# +dir /var +dir /var/lock +dir /var/log +dir /var/run +file /var/log/messages +file /var/log/wtmp + +# +# Files: /share/man +# +dir /share/man +dir /share/man/cat1 +dir /share/man/cat2 +dir /share/man/cat3 +dir /share/man/cat4 +dir /share/man/cat5 +dir /share/man/cat6 +dir /share/man/cat7 +dir /share/man/cat8 +file /share/man/cat1/ar.0 +file /share/man/cat1/chflags.0 +file /share/man/cat1/chpass.0 +file /share/man/cat1/cpp.0 +file /share/man/cat1/crontab.0 +file /share/man/cat1/emg.0 +file /share/man/cat1/groups.0 +file /share/man/cat1/hostname.0 +file /share/man/cat1/id.0 +file /share/man/cat1/la.0 +file /share/man/cat1/lcc.0 +file /share/man/cat1/ld.0 +file /share/man/cat1/passwd.0 +file /share/man/cat1/printf.0 +file /share/man/cat1/ranlib.0 +file /share/man/cat1/rz.0 +file /share/man/cat1/stty.0 +file /share/man/cat1/sz.0 +file /share/man/cat1/test.0 +file /share/man/cat1/uname.0 +file /share/man/cat1/whoami.0 +file /share/man/cat1/xargs.0 +file /share/man/cat3/vmf.0 +file /share/man/cat5/ar.0 +file /share/man/cat5/crontab.0 +file /share/man/cat5/ranlib.0 +file /share/man/cat6/adventure.0 +file /share/man/cat6/arithmetic.0 +file /share/man/cat6/backgammon.0 +file /share/man/cat6/banner.0 +file /share/man/cat6/battlestar.0 +file /share/man/cat6/bcd.0 +file /share/man/cat6/canfield.0 +file /share/man/cat6/fish.0 +file /share/man/cat6/number.0 +file /share/man/cat6/rain.0 +file /share/man/cat6/rogue.0 +file /share/man/cat6/sail.0 +file /share/man/cat6/trek.0 +file /share/man/cat6/worm.0 +file /share/man/cat6/worms.0 +file /share/man/cat6/wump.0 +file /share/man/cat8/chown.0 +file /share/man/cat8/chroot.0 +file /share/man/cat8/cron.0 +file /share/man/cat8/fdisk.0 +file /share/man/cat8/fstat.0 +file /share/man/cat8/init.0 +file /share/man/cat8/mkfs.0 +file /share/man/cat8/mknod.0 +file /share/man/cat8/mkpasswd.0 +file /share/man/cat8/mount.0 +file /share/man/cat8/pstat.0 +file /share/man/cat8/reboot.0 +file /share/man/cat8/renice.0 +file /share/man/cat8/shutdown.0 +file /share/man/cat8/sysctl.0 +file /share/man/cat8/talloc.0 +file /share/man/cat8/umount.0 +file /share/man/cat8/update.0 +file /share/man/cat8/vipw.0 + +link /share/man/cat1/rb.0 +target /share/man/cat1/rz.0 +link /share/man/cat1/rx.0 +target /share/man/cat1/rz.0 + +link /share/man/cat1/sb.0 +target /share/man/cat1/sz.0 +link /share/man/cat1/sx.0 +target /share/man/cat1/sz.0 + +link /share/man/cat8/fastboot.0 +target /share/man/cat8/reboot.0 +link /share/man/cat8/halt.0 +target /share/man/cat8/reboot.0 + +link /share/man/cat1/chfn.0 +target /share/man/cat1/chpass.0 +link /share/man/cat1/chsh.0 +target /share/man/cat1/chpass.0 diff --git a/tools/fsutil/manifest.c b/tools/fsutil/manifest.c index a41d863..da20ec2 100644 --- a/tools/fsutil/manifest.c +++ b/tools/fsutil/manifest.c @@ -23,6 +23,7 @@ */ #include #include +#include #include #include #include @@ -96,8 +97,8 @@ static char *find_link (dev_t dev, ino_t ino) /* * Add new entry to the manifest. */ -static void add_entry (manifest_t *m, int filetype, - char *path, char *link, int mode, int owner, int group) +static void add_entry (manifest_t *m, int filetype, char *path, char *link, + int mode, int owner, int group, int majr, int minr) { entry_t *e; @@ -112,8 +113,8 @@ static void add_entry (manifest_t *m, int filetype, e->mode = mode; e->owner = owner; e->group = group; - e->major = 0; - e->minor = 0; + e->major = majr; + e->minor = minr; e->link = 0; e->link = link ? strdup (link) : 0; strcpy (e->path, path); @@ -150,8 +151,8 @@ int manifest_scan (manifest_t *m, const char *dirname) /* Clear manifest header. */ m->first = 0; m->last = 0; - m->filemode = 0; - m->dirmode = 0; + m->filemode = 0664; + m->dirmode = 0775; m->owner = 0; m->group = 0; @@ -182,7 +183,7 @@ int manifest_scan (manifest_t *m, const char *dirname) switch (node->fts_info) { case FTS_D: /* Directory. */ - add_entry (m, 'd', path, 0, mode, st.st_uid, st.st_gid); + add_entry (m, 'd', path, 0, mode, st.st_uid, st.st_gid, 0, 0); break; case FTS_F: @@ -191,12 +192,12 @@ int manifest_scan (manifest_t *m, const char *dirname) /* Hard link to file. */ target = find_link (st.st_dev, st.st_ino); if (target) { - add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid); + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid, 0, 0); break; } keep_link (st.st_dev, st.st_ino, path); } - add_entry (m, 'f', path, 0, mode, st.st_uid, st.st_gid); + add_entry (m, 'f', path, 0, mode, st.st_uid, st.st_gid, 0, 0); break; case FTS_SL: @@ -205,7 +206,7 @@ int manifest_scan (manifest_t *m, const char *dirname) /* Hard link to symlink. */ target = find_link (st.st_dev, st.st_ino); if (target) { - add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid); + add_entry (m, 'l', path, target, mode, st.st_uid, st.st_gid, 0, 0); break; } keep_link (st.st_dev, st.st_ino, path); @@ -217,7 +218,7 @@ int manifest_scan (manifest_t *m, const char *dirname) break; } buf[len] = 0; - add_entry (m, 's', path, buf, mode, st.st_uid, st.st_gid); + add_entry (m, 's', path, buf, mode, st.st_uid, st.st_gid, 0, 0); break; default: @@ -277,7 +278,7 @@ void manifest_print (manifest_t *m) /* Ignore all other variants. */ continue; } - printf ("mode %o\n", mode); + printf ("mode %#o\n", mode); printf ("owner %u\n", owner); printf ("group %u\n", group); } @@ -289,8 +290,212 @@ void manifest_print (manifest_t *m) */ int manifest_load (manifest_t *m, const char *filename) { - //TODO - return 0; + FILE *fd; + char line [1024], *p, *cmd = 0, *arg = 0, *path = 0, *target = 0; + int type = 0, default_dirmode = 0775, default_filemode = 0664; + int default_owner = 0, default_group = 0; + int mode = -1, owner = -1, group = -1, majr = -1, minr = -1; + + /* Clear manifest header. */ + m->first = 0; + m->last = 0; + m->filemode = 0664; + m->dirmode = 0775; + m->owner = 0; + m->group = 0; + + /* Open file. */ + fd = fopen (filename, "r"); + if (! fd) { + perror (filename); + return 0; + } + + /* Parse the manifest file. */ + while (fgets (line, sizeof(line), fd)) { + /* Remove trailing spaces. */ + p = line + strlen(line); + while (p-- >line && (*p==' ' || *p == '\t' || *p == '\r' || *p == '\n')) + *p = 0; + + /* Remove spaces at line beginning. */ + p = line; + while (*p==' ' || *p == '\t' || *p == '\r' || *p == '\n') + ++p; + if (*p == 0) + continue; + + /* Skip comments. */ + if (*p == '#') + continue; + + /* Split into command and agrument. */ + cmd = p; + p = strchr (p, ' '); + if (p) { + *p = 0; + arg = p+1; + } else { + arg = ""; + } + + /* + * Process options. + */ + if (strcmp ("dirmode", cmd) == 0) { + if (type != 0) { +notdef: fprintf (stderr, "%s: command '%s' allowed only in default section\n", filename, cmd); + fclose (fd); + return 0; + } + default_dirmode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("filemode", cmd) == 0) { + if (type != 0) + goto notdef; + default_filemode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("owner", cmd) == 0) { + if (type != 0) + owner = strtoul (arg, 0, 0); + else + default_owner = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("group", cmd) == 0) { + if (type != 0) + group = strtoul (arg, 0, 0); + else + default_group = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("mode", cmd) == 0) { + if (type == 0) { +baddef: fprintf (stderr, "%s: command '%s' not allowed in default section\n", filename, cmd); + fclose (fd); + return 0; + } + mode = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("major", cmd) == 0) { + if (type == 0) + goto baddef; + majr = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("minor", cmd) == 0) { + if (type == 0) + goto baddef; + minr = strtoul (arg, 0, 0); + continue; + } + if (strcmp ("target", cmd) == 0) { + if (type != 'l' && type != 's') { + fprintf (stderr, "%s: command '%s' allowed only for links\n", filename, cmd); + fclose (fd); + return 0; + } + target = strdup (arg); + continue; + } + + /* + * End of section: add new object. + */ + if (type != 0) { +newobj: /* Check parameters. */ + if ((type == 'l' || type == 's') && ! target) { + fprintf (stderr, "%s: target missing for link '%s'\n", filename, path); + fclose (fd); + return 0; + } + if ((type == 'b' || type == 'c') && majr == -1) { + fprintf (stderr, "%s: major index missing for device '%s'\n", filename, path); + fclose (fd); + return 0; + } + if ((type == 'b' || type == 'c') && minr == -1) { + fprintf (stderr, "%s: minor index missing for device '%s'\n", filename, path); + fclose (fd); + return 0; + } + if (mode == -1) + mode = (type == 'd') ? default_dirmode : default_filemode; + if (owner == -1) + owner = default_owner; + if (group == -1) + group = default_group; + + /* Create new object. */ + add_entry (m, type, path, target, mode, owner, group, majr, minr); + + /* Set parameters to defaults. */ + type = 0; + free (path); + path = 0; + if (target) { + free (target); + target = 0; + } + mode = -1; + owner = -1; + group = -1; + majr = -1; + minr = -1; + if (! fd) { + /* Last object done. */ + return 1; + } + } + + /* + * Start new section. + */ + if (strcmp ("default", cmd) == 0) { + type = 0; + } + else if (strcmp ("dir", cmd) == 0) { + type = 'd'; + path = strdup (arg); + } + else if (strcmp ("file", cmd) == 0) { + type = 'f'; + path = strdup (arg); + } + else if (strcmp ("link", cmd) == 0) { + type = 'l'; + path = strdup (arg); + } + else if (strcmp ("symlink", cmd) == 0) { + type = 's'; + path = strdup (arg); + } + else if (strcmp ("bdev", cmd) == 0) { + type = 'b'; + path = strdup (arg); + } + else if (strcmp ("cdev", cmd) == 0) { + type = 'c'; + path = strdup (arg); + } + else { + fprintf (stderr, "%s: unknown command '%s'\n", filename, cmd); + fclose (fd); + return 0; + } + } + + /* Done. */ + fclose (fd); + if (type != 0) { + /* Create last object. */ + fd = 0; + goto newobj; + } + return 1; } /* diff --git a/tools/fsutil/manifest.txt b/tools/fsutil/manifest.txt index 5f29cac..c0a8a4c 100644 --- a/tools/fsutil/manifest.txt +++ b/tools/fsutil/manifest.txt @@ -4,13 +4,13 @@ default owner 0 group 0 -dirmode 775 -filemode 664 +dirmode 0775 +filemode 0664 dir /tmp file /etc/passwd -mode 444 +mode 0444 link /etc/aliases target mail/aliases From 1462eeb400f103d31655e5bc637da6e78efb4fcb Mon Sep 17 00:00:00 2001 From: Sergey Date: Sun, 3 Aug 2014 15:53:53 -0700 Subject: [PATCH 37/40] Using manifest files to create root and user filesystems. --- Makefile | 76 ++++------------------------- filesys.manifest => rootfs.manifest | 11 +++-- tools/fsutil/fsutil.c | 63 +++++++++++++++++++----- tools/fsutil/mount.c | 2 + u/README.txt | 1 + userfs.manifest | 10 ++++ 6 files changed, 82 insertions(+), 81 deletions(-) rename filesys.manifest => rootfs.manifest (99%) create mode 100644 u/README.txt create mode 100644 userfs.manifest diff --git a/Makefile b/Makefile index f697606..cf9979c 100644 --- a/Makefile +++ b/Makefile @@ -60,55 +60,6 @@ TARGETDIR = $(shell dirname $(TARGET)) TARGETNAME = $(shell basename $(TARGET)) TOPSRC = $(shell pwd) CONFIG = $(TOPSRC)/tools/configsys/config -# -# Filesystem contents. -# -BIN_FILES := $(wildcard bin/*) -SBIN_FILES := $(wildcard sbin/*) -GAMES_FILES := $(shell find games -type f ! -path '*/.*') -LIBEXEC_FILES := $(wildcard libexec/*) -LIB_FILES := lib/crt0.o lib/retroImage $(wildcard lib/*.a) -ETC_FILES = etc/rc etc/rc.local etc/ttys etc/gettytab etc/group \ - etc/passwd etc/shadow etc/fstab etc/motd etc/shells \ - etc/termcap etc/MAKEDEV etc/phones etc/remote -INC_FILES = $(wildcard include/*.h) \ - $(wildcard include/sys/*.h) \ - $(wildcard include/machine/*.h) \ - $(wildcard include/smallc/*.h) \ - $(wildcard include/smallc/sys/*.h) \ - $(wildcard include/arpa/*.h) -SHARE_FILES = share/re.help share/emg.keys share/example/Makefile \ - share/example/ashello.S share/example/chello.c \ - share/example/blkjack.bas share/example/hilow.bas \ - share/example/stars.bas share/example/prime.scm \ - share/example/fact.fth share/example/echo.S \ - share/example/stdarg.c share/example/skeleton.c \ - $(wildcard share/smallc/*) -MANFILES = share/man/ share/man/cat1/ share/man/cat2/ share/man/cat3/ \ - share/man/cat4/ share/man/cat5/ share/man/cat6/ share/man/cat7/ \ - share/man/cat8/ $(wildcard share/man/cat?/*) -ALLFILES = $(SBIN_FILES) $(ETC_FILES) $(BIN_FILES) $(LIB_FILES) $(LIBEXEC_FILES) \ - $(INC_FILES) $(SHARE_FILES) $(GAMES_FILES) \ - var/log/messages var/log/wtmp .profile -ALLDIRS = games/ sbin/ bin/ dev/ etc/ tmp/ lib/ libexec/ share/ include/ \ - var/ u/ share/example/ share/misc/ share/smallc/ \ - var/run/ var/log/ var/lock/ games/ games/lib/ include/sys/ \ - include/machine/ include/arpa/ include/smallc/ \ - include/smallc/sys/ share/misc/ share/smallc/ include/sys/ \ - games/lib/ -BDEVS = dev/rd0!b0:0 dev/rd0a!b0:1 dev/rd0b!b0:2 dev/rd0c!b0:3 dev/rd0d!b0:4 -BDEVS += dev/rd1!b1:0 dev/rd1a!b1:1 dev/rd1b!b1:2 dev/rd1c!b1:3 dev/rd1d!b1:4 -BDEVS += dev/rd2!b2:0 dev/rd2a!b2:1 dev/rd2b!b2:2 dev/rd2c!b2:3 dev/rd2d!b2:4 -BDEVS += dev/rd3!b3:0 dev/rd3a!b3:1 dev/rd3b!b3:2 dev/rd3c!b3:3 dev/rd3d!b3:4 -BDEVS += dev/swap!b4:64 dev/swap0!b4:0 dev/swap1!b4:1 dev/swap2!b4:2 - -D_CONSOLE = dev/console!c0:0 -D_MEM = dev/mem!c1:0 dev/kmem!c1:1 dev/null!c1:2 dev/zero!c1:3 -D_TTY = dev/tty!c2:0 -D_FD = dev/stdin!c3:0 dev/stdout!c3:1 dev/stderr!c3:2 -D_TEMP = dev/temp0!c4:0 dev/temp1!c4:1 dev/temp2!c4:2 - -CDEVS = $(D_CONSOLE) $(D_MEM) $(D_TTY) $(D_FD) $(D_TEMP) all: tools build kernel $(MAKE) fs @@ -132,24 +83,17 @@ lib: build: tools lib $(MAKE) -C src install -filesys.img: $(FSUTIL) $(ALLFILES) +filesys.img: $(FSUTIL) rootfs.manifest #$(ALLFILES) rm -f $@ - $(FSUTIL) -n$(FS_KBYTES) $@ - $(FSUTIL) -a $@ $(ALLDIRS) - $(FSUTIL) -a $@ $(CDEVS) - $(FSUTIL) -a $@ $(BDEVS) - $(FSUTIL) -a $@ $(ALLFILES) - $(FSUTIL) -a $@ $(MANFILES) + $(FSUTIL) -n$(FS_KBYTES) -Mrootfs.manifest $@ . swap.img: dd if=/dev/zero of=$@ bs=1k count=$(SWAP_KBYTES) -user.img: $(FSUTIL) +user.img: $(FSUTIL) userfs.manifest ifneq ($(U_KBYTES), 0) rm -f $@ - $(FSUTIL) -n$(U_KBYTES) $@ - (cd u; find . -type d -exec ../$(FSUTIL) -a ../$@ '{}/' \;) - (cd u; find . -type f -exec ../$(FSUTIL) -a ../$@ '{}' \+) + $(FSUTIL) -n$(U_KBYTES) -Muserfs.manifest $@ u endif sdcard.rd: filesys.img swap.img user.img @@ -184,20 +128,20 @@ cleanall: clean rm -f var/log/aculog rm -rf var/lock -installfs: filesys.img +installfs: filesys.img ifdef SDCARD - sudo dd bs=32k if=sdcard.rd of=$(SDCARD) + sudo dd bs=32k if=sdcard.rd of=$(SDCARD) else - @echo "Error: No SDCARD defined." + @echo "Error: No SDCARD defined." endif # TODO: make it relative to Target installflash: - sudo pic32prog sys/pic32/fubarino/unix.hex + sudo pic32prog sys/pic32/fubarino/unix.hex # TODO: make it relative to Target installboot: - sudo pic32prog sys/pic32/fubarino/bootloader.hex + sudo pic32prog sys/pic32/fubarino/bootloader.hex -.profile: etc/root/dot.profile +.profile: etc/root/dot.profile cp etc/root/dot.profile .profile diff --git a/filesys.manifest b/rootfs.manifest similarity index 99% rename from filesys.manifest rename to rootfs.manifest index 6910753..47cc8d6 100644 --- a/filesys.manifest +++ b/rootfs.manifest @@ -34,12 +34,15 @@ minor 1 cdev /dev/null major 1 minor 2 +mode 666 cdev /dev/zero major 1 minor 3 +mode 666 cdev /dev/tty major 2 minor 0 +mode 666 cdev /dev/stdin major 3 minor 0 @@ -350,14 +353,14 @@ target /bin/chpass link /bin/chsh target /bin/chpass -file /bin/rb +link /bin/rb target /bin/rz -file /bin/rx +link /bin/rx target /bin/rz -file /bin/sb +link /bin/sb target /bin/sz -file /bin/sx +link /bin/sx target /bin/sz # diff --git a/tools/fsutil/fsutil.c b/tools/fsutil/fsutil.c index 721b467..ea3aa05 100644 --- a/tools/fsutil/fsutil.c +++ b/tools/fsutil/fsutil.c @@ -75,7 +75,7 @@ static void print_help (char *progname) printf ("%s\n", program_version); printf ("This program is free software; it comes with ABSOLUTELY NO WARRANTY;\n" - "see the GNU General Public License for more details.\n"); + "see the BSD 3-Clause License for more details.\n"); printf ("\n"); printf ("Usage:\n"); printf (" %s [--verbose] filesys.img\n", progname); @@ -474,6 +474,8 @@ void add_hardlink (fs_t *fs, const char *path, const char *link) fprintf (stderr, "%s: link failed\n", path); return; } + source.nlink++; + fs_inode_save (&source, 1); } /* @@ -521,6 +523,7 @@ void add_contents (fs_t *fs, const char *dirname, const char *manifest) void *cursor; char *path, *link; int filetype, mode, owner, group, majr, minr; + int ndirs = 0, nfiles = 0, nlinks = 0, nsymlinks = 0, ndevs = 0; if (manifest) { /* Load manifest from file. */ @@ -545,24 +548,34 @@ void add_contents (fs_t *fs, const char *dirname, const char *manifest) switch (filetype) { case 'd': add_directory (fs, path, mode, owner, group); + ndirs++; break; case 'f': add_file (fs, path, dirname, mode, owner, group); + nfiles++; break; case 'l': add_hardlink (fs, path, link); + nlinks++; break; case 's': add_symlink (fs, path, link, mode, owner, group); + nsymlinks++; break; case 'b': add_device (fs, path, mode, owner, group, 'b', majr, minr); + ndevs++; break; case 'c': add_device (fs, path, mode, owner, group, 'c', majr, minr); + ndevs++; break; } } + fs_sync (fs, 0); + fs_close (fs); + printf ("Installed %u directories, %u files, %u devices, %u links, %u symlinks\n", + ndirs, nfiles, ndevs, nlinks, nsymlinks); } int main (int argc, char **argv) @@ -574,7 +587,7 @@ int main (int argc, char **argv) const char *manifest = 0; for (;;) { - key = getopt_long (argc, argv, "vaxmMSn:cfs:", + key = getopt_long (argc, argv, "vaxmSn:cfs:M:", program_options, 0); if (key == -1) break; @@ -622,19 +635,23 @@ int main (int argc, char **argv) } } i = optind; - if ((! add && ! mount && ! newfs && i != argc-1) || - (add && i >= argc) || - (newfs && i != argc-1 && i != argc-2) || - (mount && i != argc-2) || - (extract + newfs + check + add + mount + scan > 1) || - (newfs && kbytes < BSDFS_BSIZE * 10 / 1024)) - { + if (extract + newfs + check + add + mount + scan > 1) { print_help (argv[0]); return -1; } if (newfs) { /* Create new filesystem. */ + if (i != argc-1 && i != argc-2) { + print_help (argv[0]); + return -1; + } + if (kbytes < BSDFS_BSIZE * 10 / 1024) { + /* Need at least 10 blocks. */ + fprintf (stderr, "%s: too small\n", argv[i]); + return -1; + } + if (! fs_create (&fs, argv[i], kbytes, swap_kbytes)) { fprintf (stderr, "%s: cannot create filesystem\n", argv[i]); return -1; @@ -652,6 +669,10 @@ int main (int argc, char **argv) if (check) { /* Check filesystem for errors, and optionally fix them. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } if (! fs_open (&fs, argv[i], fix)) { fprintf (stderr, "%s: cannot open\n", argv[i]); return -1; @@ -663,6 +684,10 @@ int main (int argc, char **argv) if (scan) { /* Create a manifest from directory contents. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } if (! manifest_scan (&m, argv[i])) { fprintf (stderr, "%s: cannot read\n", argv[i]); return -1; @@ -672,6 +697,10 @@ int main (int argc, char **argv) } /* Add or extract or info. */ + if (i >= argc) { + print_help (argv[0]); + return -1; + } if (! fs_open (&fs, argv[i], (add + mount != 0))) { fprintf (stderr, "%s: cannot open\n", argv[i]); return -1; @@ -679,6 +708,10 @@ int main (int argc, char **argv) if (extract) { /* Extract all files to current directory. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } if (! fs_inode_get (&fs, &inode, BSDFS_ROOT_INODE)) { fprintf (stderr, "%s: cannot get inode 1\n", argv[i]); return -1; @@ -690,6 +723,10 @@ int main (int argc, char **argv) if (add) { /* Add files i+1..argc-1 to filesystem. */ + if (i >= argc) { + print_help (argv[0]); + return -1; + } while (++i < argc) add_object (&fs, argv[i]); fs_sync (&fs, 0); @@ -699,14 +736,18 @@ int main (int argc, char **argv) if (mount) { /* Mount the filesystem. */ - if (++i >= argc) { + if (i != argc-2) { print_help (argv[0]); return -1; } - return fs_mount(&fs, argv[i]); + return fs_mount(&fs, argv[i+1]); } /* Print the structure of flesystem. */ + if (i != argc-1) { + print_help (argv[0]); + return -1; + } fs_print (&fs, stdout); if (verbose) { printf ("--------\n"); diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index 69f5a60..fb4b256 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -465,6 +465,8 @@ int op_link(const char *path, const char *newpath) printlog("--- link failed\n"); return -EIO; } + source.nlink++; + fs_inode_save (&source, 1); return 0; } diff --git a/u/README.txt b/u/README.txt new file mode 100644 index 0000000..aa96d61 --- /dev/null +++ b/u/README.txt @@ -0,0 +1 @@ +User filesystem. diff --git a/userfs.manifest b/userfs.manifest new file mode 100644 index 0000000..4de6f25 --- /dev/null +++ b/userfs.manifest @@ -0,0 +1,10 @@ +# +# Manifest file for user filesystem. +# +default +owner 0 +group 0 +dirmode 0775 +filemode 0664 + +file README.txt From 83a999be0adc14428ce81f6bd885671cfdcd5a01 Mon Sep 17 00:00:00 2001 From: Matt Jenkins Date: Wed, 27 Aug 2014 23:13:26 +0100 Subject: [PATCH 38/40] Added definitions for picadillo, and spi sram device --- sys/include/rd_spirams.h | 9 ++ sys/kernel/rdisk.c | 7 + sys/pic32/cfg/picadillo.map | 76 +++++++++ sys/pic32/cfg/spirams.dev | 184 ++++++++++++++++++++++ sys/pic32/gcc-config.mk | 7 + sys/pic32/picadillo/PICADILLO | 4 +- sys/pic32/picadillo_rambo/Makefile | 95 +++++++++++ sys/pic32/picadillo_rambo/PICADILLO_RAMBO | 22 +++ sys/pic32/spi_bus.c | 4 +- 9 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 sys/include/rd_spirams.h create mode 100644 sys/pic32/cfg/picadillo.map create mode 100644 sys/pic32/cfg/spirams.dev create mode 100644 sys/pic32/picadillo_rambo/Makefile create mode 100644 sys/pic32/picadillo_rambo/PICADILLO_RAMBO diff --git a/sys/include/rd_spirams.h b/sys/include/rd_spirams.h new file mode 100644 index 0000000..8ab721d --- /dev/null +++ b/sys/include/rd_spirams.h @@ -0,0 +1,9 @@ +#ifndef _SPIRAMS_H +#define _SPIRAMS_H + +extern int spirams_size(int unit); +extern int spirams_read(int unit, unsigned int offset, char *data, unsigned int bcount); +extern int spirams_write (int unit, unsigned offset, char *data, unsigned bcount); +extern void spirams_preinit (int unit); + +#endif diff --git a/sys/kernel/rdisk.c b/sys/kernel/rdisk.c index 5a91f93..6752eaf 100644 --- a/sys/kernel/rdisk.c +++ b/sys/kernel/rdisk.c @@ -43,6 +43,9 @@ extern int sdsize(int unit); #ifdef MRAMS_ENABLED #include #endif +#ifdef SPIRAMS_ENABLED +#include +#endif int no_deinit(int u) { return 0; } void no_preinit(int u) { return; } @@ -85,6 +88,10 @@ const struct diskentry disks[] = { {mrams_preinit, no_init, no_deinit, no_open, mrams_size, mrams_read, mrams_write, 0, RD_DEFAULT}, #endif +#ifdef SPIRAMS_ENABLED + {spirams_preinit, no_init, no_deinit, no_open, spirams_size, spirams_read, spirams_write, 0, RD_DEFAULT}, +#endif + }; #define NRDSK sizeof(disks)/sizeof(struct diskentry) diff --git a/sys/pic32/cfg/picadillo.map b/sys/pic32/cfg/picadillo.map new file mode 100644 index 0000000..e23e884 --- /dev/null +++ b/sys/pic32/cfg/picadillo.map @@ -0,0 +1,76 @@ +# Format is: silk port pin +# silk is the name of the pin, port and pin is what it maps to. +0 F 2 +1 F 8 +2 E 8 +3 A 3 +4 F 3 +5 G 15 +6 D 11 +7 E 9 +8 D 15 +9 D 3 +10 C 4 +11 D 10 +12 D 9 +13 D 0 +A0 B 0 +14 B 0 +A1 B 1 +15 B 1 +A2 B 2 +16 B 2 +A3 B 3 +17 B 3 +A4 B 4 +18 B 4 +A5 B 5 +19 B 5 +A6 B 6 +20 B 6 +A7 B 7 +21 B 7 +A8 B 8 +22 B 8 +A9 B 9 +23 B 9 +A10 B 10 +24 B 10 +A11 B 11 +25 B 11 +26 A 0 +27 A 1 +28 A 4 +29 A 5 +30 A 2 +31 D 1 +32 D 2 +A14 B 14 +33 B 14 +34 D 14 +35 D 8 +36 A 6 +37 A 7 +38 G 14 +39 G 12 +40 G 13 +41 A 9 +42 A 10 +43 B 12 +44 B 13 +45 C 2 +46 C 13 +47 C 1 +48 G 9 +49 F 4 +50 F 13 +51 F 5 +52 F 5 +53 A 15 +54 A 14 +55 G 7 +56 G 8 +57 G 6 + + + diff --git a/sys/pic32/cfg/spirams.dev b/sys/pic32/cfg/spirams.dev new file mode 100644 index 0000000..bf896ff --- /dev/null +++ b/sys/pic32/cfg/spirams.dev @@ -0,0 +1,184 @@ +always + define SPIRAMS_ENABLED + file rd_spirams.o + require rdisk + require spibus + define SPIRAMS_CHIPSIZE 128 +end always + +option chips + define SPIRAMS_CHIPS %1 +end option + +option port + define SPIRAMS_PORT %1 +end option + +option chipsize + define SPIRAMS_CHIPSIZE %1 +end option + +option mhz + define SPIRAMS_MHZ %1 +end option + +option cs0 + define SPIRAMS_CS0_PORT $TRIS(%1) + define SPIRAMS_CS0_PIN $PIN(%1) +end option + +option cs1 + define SPIRAMS_CS1_PORT $TRIS(%1) + define SPIRAMS_CS1_PIN $PIN(%1) +end option + +option cs2 + define SPIRAMS_CS2_PORT $TRIS(%1) + define SPIRAMS_CS2_PIN $PIN(%1) +end option + +option cs3 + define SPIRAMS_CS3_PORT $TRIS(%1) + define SPIRAMS_CS3_PIN $PIN(%1) +end option + +option cs4 + define SPIRAMS_CS4_PORT $TRIS(%1) + define SPIRAMS_CS4_PIN $PIN(%1) +end option + +option cs5 + define SPIRAMS_CS5_PORT $TRIS(%1) + define SPIRAMS_CS5_PIN $PIN(%1) +end option + +option cs6 + define SPIRAMS_CS6_PORT $TRIS(%1) + define SPIRAMS_CS6_PIN $PIN(%1) +end option + +option cs7 + define SPIRAMS_CS7_PORT $TRIS(%1) + define SPIRAMS_CS7_PIN $PIN(%1) +end option + +option cs8 + define SPIRAMS_CS8_PORT $TRIS(%1) + define SPIRAMS_CS8_PIN $PIN(%1) +end option + +option cs9 + define SPIRAMS_CS9_PORT $TRIS(%1) + define SPIRAMS_CS9_PIN $PIN(%1) +end option + +option cs10 + define SPIRAMS_CS10_PORT $TRIS(%1) + define SPIRAMS_CS10_PIN $PIN(%1) +end option + +option cs11 + define SPIRAMS_CS11_PORT $TRIS(%1) + define SPIRAMS_CS11_PIN $PIN(%1) +end option + +option cs12 + define SPIRAMS_CS12_PORT $TRIS(%1) + define SPIRAMS_CS12_PIN $PIN(%1) +end option + +option cs13 + define SPIRAMS_CS13_PORT $TRIS(%1) + define SPIRAMS_CS13_PIN $PIN(%1) +end option + +option cs14 + define SPIRAMS_CS14_PORT $TRIS(%1) + define SPIRAMS_CS14_PIN $PIN(%1) +end option + +option cs15 + define SPIRAMS_CS15_PORT $TRIS(%1) + define SPIRAMS_CS15_PIN $PIN(%1) +end option + +option led0 + define SPIRAMS_LED0_PORT $TRIS(%1) + define SPIRAMS_LED0_PIN $PIN(%1) +end option + +option led1 + define SPIRAMS_LED1_PORT $TRIS(%1) + define SPIRAMS_LED1_PIN $PIN(%1) +end option + +option led2 + define SPIRAMS_LED2_PORT $TRIS(%1) + define SPIRAMS_LED2_PIN $PIN(%1) +end option + +option led3 + define SPIRAMS_LED3_PORT $TRIS(%1) + define SPIRAMS_LED3_PIN $PIN(%1) +end option + +option led4 + define SPIRAMS_LED4_PORT $TRIS(%1) + define SPIRAMS_LED4_PIN $PIN(%1) +end option + +option led5 + define SPIRAMS_LED5_PORT $TRIS(%1) + define SPIRAMS_LED5_PIN $PIN(%1) +end option + +option led6 + define SPIRAMS_LED6_PORT $TRIS(%1) + define SPIRAMS_LED6_PIN $PIN(%1) +end option + +option led7 + define SPIRAMS_LED7_PORT $TRIS(%1) + define SPIRAMS_LED7_PIN $PIN(%1) +end option + +option led8 + define SPIRAMS_LED8_PORT $TRIS(%1) + define SPIRAMS_LED8_PIN $PIN(%1) +end option + +option led9 + define SPIRAMS_LED9_PORT $TRIS(%1) + define SPIRAMS_LED9_PIN $PIN(%1) +end option + +option led10 + define SPIRAMS_LED10_PORT $TRIS(%1) + define SPIRAMS_LED10_PIN $PIN(%1) +end option + +option led11 + define SPIRAMS_LED11_PORT $TRIS(%1) + define SPIRAMS_LED11_PIN $PIN(%1) +end option + +option led12 + define SPIRAMS_LED12_PORT $TRIS(%1) + define SPIRAMS_LED12_PIN $PIN(%1) +end option + +option led13 + define SPIRAMS_LED13_PORT $TRIS(%1) + define SPIRAMS_LED13_PIN $PIN(%1) +end option + +option led14 + define SPIRAMS_LED14_PORT $TRIS(%1) + define SPIRAMS_LED14_PIN $PIN(%1) +end option + +option led15 + define SPIRAMS_LED15_PORT $TRIS(%1) + define SPIRAMS_LED15_PIN $PIN(%1) +end option + diff --git a/sys/pic32/gcc-config.mk b/sys/pic32/gcc-config.mk index 47efd99..ac5fdbe 100644 --- a/sys/pic32/gcc-config.mk +++ b/sys/pic32/gcc-config.mk @@ -47,6 +47,13 @@ ifndef GCCPREFIX $(error Unable to locate any GCC MIPS toolchain!) endif +# UECIDE on Linux +ifneq (,$(wildcard $UECIDE/cores/chipKIT)) + AVRDUDE = $UECIDE/cores/chipKIT/tools/linux64/avrdude \ + -C $UECIDE/cores/chipKIT/tools/linux64/avrdude.conf -V \ + -P /dev/ttyUSB* +endif + # chipKIT MPIDE on Mac OS X ifneq (,$(wildcard /Applications/Mpide.app/Contents/Resources/Java/hardware/tools/avr)) AVRDUDE = /Applications/Mpide.app/Contents/Resources/Java/hardware/tools/avr/bin/avrdude \ diff --git a/sys/pic32/picadillo/PICADILLO b/sys/pic32/picadillo/PICADILLO index bc50dc9..a23858b 100644 --- a/sys/pic32/picadillo/PICADILLO +++ b/sys/pic32/picadillo/PICADILLO @@ -3,7 +3,7 @@ # =================== core pic32mx7 -mapping generic +mapping picadillo linker bootloader-max32 device kernel cpu_khz=80000 bus_khz=80000 @@ -12,7 +12,7 @@ device console device=tty0 device uart1 baud=115200 device rdisk -device sd0 port=2 cs=G9 +device sd0 port=2 cs=48 device gpio device adc diff --git a/sys/pic32/picadillo_rambo/Makefile b/sys/pic32/picadillo_rambo/Makefile new file mode 100644 index 0000000..e7bddc7 --- /dev/null +++ b/sys/pic32/picadillo_rambo/Makefile @@ -0,0 +1,95 @@ +BUILDPATH = ../../../tools/configsys/../../sys/pic32 +H = ../../../tools/configsys/../../sys/include +M = ../../../tools/configsys/../../sys/pic32 +S = ../../../tools/configsys/../../sys/kernel + +vpath %.c $(M):$(S) +vpath %.S $(M):$(S) + +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_spirams.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +EXTRA_TARGETS = + +DEFS += -DADC_ENABLED=YES +DEFS += -DBUS_DIV=1 +DEFS += -DBUS_KHZ=80000 +DEFS += -DCONSOLE_DEVICE=tty0 +DEFS += -DCPU_IDIV=2 +DEFS += -DCPU_KHZ=80000 +DEFS += -DCPU_MUL=20 +DEFS += -DCPU_ODIV=1 +DEFS += -DCRYSTAL=8 +DEFS += -DDC0_DEBUG=DEVCFG0_DEBUG_DISABLED +DEFS += -DDC0_ICE=0 +DEFS += -DDC1_CKM=0 +DEFS += -DDC1_CKS=0 +DEFS += -DDC1_FNOSC=DEVCFG1_FNOSC_PRIPLL +DEFS += -DDC1_IESO=DEVCFG1_IESO +DEFS += -DDC1_OSCIOFNC=0 +DEFS += -DDC1_PBDIV=DEVCFG1_FPBDIV_1 +DEFS += -DDC1_POSCMOD=DEVCFG1_POSCMOD_HS +DEFS += -DDC1_SOSC=0 +DEFS += -DDC1_WDTEN=0 +DEFS += -DDC1_WDTPS=DEVCFG1_WDTPS_1 +DEFS += -DDC2_PLLIDIV=DEVCFG2_FPLLIDIV_2 +DEFS += -DDC2_PLLMUL=DEVCFG2_FPLLMUL_20 +DEFS += -DDC2_PLLODIV=DEVCFG2_FPLLODIV_1 +DEFS += -DDC2_UPLL=0 +DEFS += -DDC2_UPLLIDIV=DEVCFG2_UPLLIDIV_2 +DEFS += -DDC3_CAN=DEVCFG3_FCANIO +DEFS += -DDC3_ETH=DEVCFG3_FETHIO +DEFS += -DDC3_MII=DEVCFG3_FMIIEN +DEFS += -DDC3_SRS=DEVCFG3_FSRSSEL_7 +DEFS += -DDC3_USBID=DEVCFG3_FUSBIDIO +DEFS += -DDC3_USERID=0xffff +DEFS += -DDC3_VBUSON=DEVCFG3_FVBUSONIO +DEFS += -DEXEC_AOUT +DEFS += -DEXEC_ELF +DEFS += -DEXEC_SCRIPT +DEFS += -DGPIO_ENABLED=YES +DEFS += -DKERNEL +DEFS += -DPARTITION="spirams0:sa@1500" +DEFS += -DPIC32MX7 +DEFS += -DSD0_CS_PIN=9 +DEFS += -DSD0_CS_PORT=TRISG +DEFS += -DSD0_PORT=2 +DEFS += -DSPIRAMS_CHIPS=13 +DEFS += -DSPIRAMS_CHIPSIZE=128 +DEFS += -DSPIRAMS_CS0_PIN=0 +DEFS += -DSPIRAMS_CS0_PORT=TRISA +DEFS += -DSPIRAMS_CS10_PIN=6 +DEFS += -DSPIRAMS_CS10_PORT=TRISA +DEFS += -DSPIRAMS_CS11_PIN=7 +DEFS += -DSPIRAMS_CS11_PORT=TRISA +DEFS += -DSPIRAMS_CS12_PIN=14 +DEFS += -DSPIRAMS_CS12_PORT=TRISG +DEFS += -DSPIRAMS_CS1_PIN=1 +DEFS += -DSPIRAMS_CS1_PORT=TRISA +DEFS += -DSPIRAMS_CS2_PIN=4 +DEFS += -DSPIRAMS_CS2_PORT=TRISA +DEFS += -DSPIRAMS_CS3_PIN=5 +DEFS += -DSPIRAMS_CS3_PORT=TRISA +DEFS += -DSPIRAMS_CS4_PIN=2 +DEFS += -DSPIRAMS_CS4_PORT=TRISA +DEFS += -DSPIRAMS_CS5_PIN=1 +DEFS += -DSPIRAMS_CS5_PORT=TRISD +DEFS += -DSPIRAMS_CS6_PIN=2 +DEFS += -DSPIRAMS_CS6_PORT=TRISD +DEFS += -DSPIRAMS_CS7_PIN=14 +DEFS += -DSPIRAMS_CS7_PORT=TRISB +DEFS += -DSPIRAMS_CS8_PIN=14 +DEFS += -DSPIRAMS_CS8_PORT=TRISD +DEFS += -DSPIRAMS_CS9_PIN=8 +DEFS += -DSPIRAMS_CS9_PORT=TRISD +DEFS += -DSPIRAMS_ENABLED +DEFS += -DSPIRAMS_PORT=4 +DEFS += -DUART1_BAUD=115200 +DEFS += -DUART1_ENABLED=YES +DEFS += -DUCB_METER + + +LDSCRIPT = ../../../tools/configsys/../../sys/pic32/cfg/bootloader-max32.ld + +CONFIG = PICADILLO_RAMBO +CONFIGPATH = ../../../tools/configsys + +include ../../../tools/configsys/../../sys/pic32/kernel-post.mk diff --git a/sys/pic32/picadillo_rambo/PICADILLO_RAMBO b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO new file mode 100644 index 0000000..415c6d8 --- /dev/null +++ b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO @@ -0,0 +1,22 @@ +# +# Picadillo 35T board +# =================== + +core pic32mx7 +mapping picadillo +linker bootloader-max32 + +device kernel cpu_khz=80000 bus_khz=80000 + +device console device=tty0 +device uart1 baud=115200 + +device rdisk +device sd0 port=2 cs=48 +device spirams0 port=4 chips=13 cs0=26 cs1=27 cs2=28 cs3=29 cs4=30 cs5=31 cs6=32 cs7=33 cs8=34 cs9=35 cs10=36 cs11=37 cs12=38 + +option PARTITION=spirams0:sa@1500 + +device gpio +device adc +device foreignbootloader diff --git a/sys/pic32/spi_bus.c b/sys/pic32/spi_bus.c index 130478c..b9e0574 100644 --- a/sys/pic32/spi_bus.c +++ b/sys/pic32/spi_bus.c @@ -8,7 +8,7 @@ #define NSPI 4 /* Ports SPI1...SPI4 */ -#define MAXSPIDEV 10 +#define MAXSPIDEV 20 struct spi_dev spi_devices[MAXSPIDEV]; @@ -616,7 +616,7 @@ char *spi_name(int dno) return "SPI?"; if(spi_devices[dno].bus==NULL) - return "SPI?"; + return "NO SPI BUS"; if(spi_devices[dno].bus == (struct spireg *)&SPI1CON) return "SPI1"; From 9adca14b87e1897779f4b6e9ed0c56f20f4d74b1 Mon Sep 17 00:00:00 2001 From: Matt Jenkins Date: Sat, 30 Aug 2014 21:17:16 +0100 Subject: [PATCH 39/40] Added hx8357 TFT driver for PICadillo --- sys/include/fonts/default.h | 259 +++ sys/include/fonts/topaz.h | 2307 +++++++++++++++++++++ sys/include/fonts/vga.h | 1833 ++++++++++++++++ sys/include/hx8357.h | 21 + sys/pic32/cfg/hxtft.dev | 4 + sys/pic32/devsw.c | 12 + sys/pic32/hx8357.c | 774 +++++++ sys/pic32/machdep.c | 7 + sys/pic32/picadillo_rambo/Makefile | 15 +- sys/pic32/picadillo_rambo/PICADILLO_RAMBO | 7 +- sys/pic32/rd_spirams.c | 438 ++++ 11 files changed, 5670 insertions(+), 7 deletions(-) create mode 100644 sys/include/fonts/default.h create mode 100644 sys/include/fonts/topaz.h create mode 100644 sys/include/fonts/vga.h create mode 100644 sys/include/hx8357.h create mode 100644 sys/pic32/cfg/hxtft.dev create mode 100644 sys/pic32/hx8357.c create mode 100644 sys/pic32/rd_spirams.c diff --git a/sys/include/fonts/default.h b/sys/include/fonts/default.h new file mode 100644 index 0000000..fe80ee6 --- /dev/null +++ b/sys/include/fonts/default.h @@ -0,0 +1,259 @@ +const unsigned char Default[] = { + 0x08, 0x01, 0x00, 0xFF, 1, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x1F, 0x15, 0x1F, 0x1B, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x1F, 0x15, 0x1F, 0x11, 0x1B, 0x0E, 0x00, + 0x06, 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0E, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x0E, 0x1F, 0x1F, 0x0E, 0x04, 0x00, + 0x06, 0x0E, 0x0A, 0x1F, 0x15, 0x1F, 0x04, 0x0E, 0x00, + 0x06, 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x04, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x0E, 0x0E, 0x04, 0x00, 0x00, + 0x06, 0x1F, 0x1F, 0x1B, 0x11, 0x11, 0x1B, 0x1F, 0x1F, + 0x06, 0x00, 0x00, 0x04, 0x0A, 0x0A, 0x04, 0x00, 0x00, + 0x06, 0x1F, 0x1F, 0x1B, 0x15, 0x15, 0x1B, 0x1F, 0x1F, + 0x06, 0x00, 0x1C, 0x18, 0x16, 0x05, 0x05, 0x02, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x04, 0x1F, 0x04, 0x00, + 0x06, 0x1E, 0x12, 0x1E, 0x02, 0x02, 0x02, 0x03, 0x00, + 0x06, 0x1E, 0x12, 0x1E, 0x12, 0x12, 0x1A, 0x03, 0x00, + 0x06, 0x04, 0x15, 0x0E, 0x1B, 0x1B, 0x0E, 0x15, 0x04, + 0x06, 0x01, 0x03, 0x0F, 0x1F, 0x0F, 0x03, 0x01, 0x00, + 0x06, 0x10, 0x18, 0x1E, 0x1F, 0x1E, 0x18, 0x10, 0x00, + 0x06, 0x04, 0x0E, 0x15, 0x04, 0x15, 0x0E, 0x04, 0x00, + 0x06, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x1B, 0x00, + 0x06, 0x1E, 0x15, 0x15, 0x16, 0x14, 0x14, 0x14, 0x00, + 0x06, 0x0C, 0x12, 0x0A, 0x14, 0x08, 0x12, 0x12, 0x0C, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, + 0x06, 0x04, 0x0E, 0x15, 0x04, 0x15, 0x0E, 0x04, 0x1F, + 0x06, 0x00, 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x04, 0x15, 0x0E, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x08, 0x1F, 0x08, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x04, 0x02, 0x1F, 0x02, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x0A, 0x1F, 0x1F, 0x0A, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x0E, 0x1F, 0x1F, 0x00, 0x00, + 0x06, 0x00, 0x1F, 0x1F, 0x0E, 0x04, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, + 0x06, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A, 0x00, + 0x06, 0x04, 0x1E, 0x05, 0x0E, 0x14, 0x0F, 0x04, 0x00, + 0x06, 0x03, 0x13, 0x08, 0x04, 0x02, 0x19, 0x18, 0x00, + 0x06, 0x02, 0x05, 0x05, 0x02, 0x15, 0x09, 0x16, 0x00, + 0x06, 0x0C, 0x0C, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02, 0x00, + 0x06, 0x04, 0x15, 0x0E, 0x1F, 0x0E, 0x15, 0x04, 0x00, + 0x06, 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x04, 0x02, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, + 0x06, 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x19, 0x15, 0x13, 0x11, 0x0E, 0x00, + 0x06, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x10, 0x0E, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x1F, 0x10, 0x08, 0x0C, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x08, 0x0C, 0x0A, 0x09, 0x1F, 0x08, 0x08, 0x00, + 0x06, 0x1F, 0x01, 0x0F, 0x10, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x1C, 0x02, 0x01, 0x0F, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x1F, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x1E, 0x10, 0x08, 0x07, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x10, 0x08, 0x04, 0x02, 0x04, 0x08, 0x10, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x10, 0x08, 0x04, 0x02, 0x00, + 0x06, 0x0E, 0x11, 0x10, 0x0C, 0x04, 0x00, 0x04, 0x00, + 0x06, 0x0E, 0x11, 0x15, 0x1D, 0x0D, 0x01, 0x1E, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x11, 0x11, 0x0F, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0F, 0x00, + 0x06, 0x1F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x1F, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x1E, 0x11, 0x01, 0x01, 0x19, 0x11, 0x1E, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x1C, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, + 0x06, 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x00, + 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x00, + 0x06, 0x11, 0x1B, 0x15, 0x15, 0x15, 0x11, 0x11, 0x00, + 0x06, 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x15, 0x09, 0x16, 0x00, + 0x06, 0x0F, 0x11, 0x11, 0x0F, 0x05, 0x09, 0x11, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x0E, 0x10, 0x11, 0x0E, 0x00, + 0x06, 0x1F, 0x15, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A, 0x00, + 0x06, 0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11, 0x00, + 0x06, 0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x1F, 0x10, 0x08, 0x0E, 0x02, 0x01, 0x1F, 0x00, + 0x06, 0x1E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x1E, 0x00, + 0x06, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00, + 0x06, 0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x06, 0x06, 0x06, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x01, 0x01, 0x0D, 0x13, 0x11, 0x13, 0x0D, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x10, 0x10, 0x16, 0x19, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x0E, 0x00, + 0x06, 0x08, 0x14, 0x04, 0x0E, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x19, 0x19, 0x16, 0x10, 0x0E, + 0x06, 0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x08, 0x00, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00, + 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x0B, 0x15, 0x15, 0x15, 0x15, 0x00, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x13, 0x0D, 0x01, 0x01, + 0x06, 0x00, 0x00, 0x16, 0x19, 0x19, 0x16, 0x10, 0x10, + 0x06, 0x00, 0x00, 0x0D, 0x13, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x01, 0x0E, 0x10, 0x0F, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x14, 0x08, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, + 0x06, 0x00, 0x00, 0x11, 0x11, 0x1E, 0x10, 0x11, 0x0E, + 0x06, 0x00, 0x00, 0x1F, 0x08, 0x04, 0x02, 0x1F, 0x00, + 0x06, 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, + 0x06, 0x04, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x02, 0x04, 0x04, 0x08, 0x04, 0x04, 0x02, 0x00, + 0x06, 0x02, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x0E, 0x1B, 0x11, 0x11, 0x1F, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x01, 0x01, 0x11, 0x0E, 0x08, 0x06, + 0x06, 0x00, 0x11, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x18, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x1F, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x11, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x03, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x0C, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x08, 0x0C, 0x00, + 0x06, 0x1F, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x11, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x03, 0x00, 0x0E, 0x11, 0x1F, 0x01, 0x1E, 0x00, + 0x06, 0x14, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x0C, 0x12, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x06, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x0A, 0x00, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, + 0x06, 0x04, 0x00, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, + 0x06, 0x0C, 0x00, 0x0F, 0x01, 0x07, 0x01, 0x0F, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x08, 0x1E, 0x09, 0x1E, 0x00, + 0x06, 0x1C, 0x0A, 0x09, 0x1F, 0x09, 0x09, 0x19, 0x00, + 0x06, 0x0E, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x12, 0x00, 0x12, 0x12, 0x12, 0x1C, 0x10, 0x0E, + 0x06, 0x11, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x11, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x05, 0x05, 0x1F, 0x04, 0x04, + 0x06, 0x0C, 0x1A, 0x12, 0x07, 0x02, 0x12, 0x1F, 0x00, + 0x06, 0x1B, 0x1B, 0x0E, 0x1F, 0x04, 0x1F, 0x04, 0x04, + 0x06, 0x07, 0x09, 0x09, 0x07, 0x09, 0x1D, 0x09, 0x09, + 0x06, 0x18, 0x14, 0x04, 0x0E, 0x04, 0x04, 0x05, 0x03, + 0x06, 0x18, 0x00, 0x06, 0x08, 0x0E, 0x09, 0x1E, 0x00, + 0x06, 0x18, 0x00, 0x0C, 0x08, 0x08, 0x08, 0x1C, 0x00, + 0x06, 0x00, 0x18, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x18, 0x00, 0x11, 0x11, 0x19, 0x16, 0x00, + 0x06, 0x00, 0x1E, 0x00, 0x0E, 0x12, 0x12, 0x12, 0x00, + 0x06, 0x1F, 0x00, 0x13, 0x17, 0x1D, 0x19, 0x11, 0x00, + 0x06, 0x0E, 0x09, 0x09, 0x1E, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x0E, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x04, 0x06, 0x01, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00, + 0x06, 0x01, 0x11, 0x09, 0x1D, 0x12, 0x19, 0x04, 0x1C, + 0x06, 0x01, 0x11, 0x09, 0x15, 0x1A, 0x1D, 0x10, 0x10, + 0x06, 0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x00, 0x14, 0x0A, 0x05, 0x0A, 0x14, 0x00, 0x00, + 0x06, 0x00, 0x05, 0x0A, 0x14, 0x0A, 0x05, 0x00, 0x00, + 0x06, 0x04, 0x11, 0x04, 0x11, 0x04, 0x11, 0x04, 0x11, + 0x06, 0x0A, 0x15, 0x0A, 0x15, 0x0A, 0x15, 0x0A, 0x15, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x18, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x04, 0x1C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1C, 0x04, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x17, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x04, 0x14, 0x14, 0x14, 0x14, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x17, 0x00, 0x17, 0x14, 0x14, 0x14, + 0x06, 0x08, 0x08, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1C, 0x00, 0x00, 0x00, + 0x06, 0x08, 0x08, 0x18, 0x08, 0x18, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x18, 0x08, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x14, 0x14, 0x14, + 0x06, 0x14, 0x14, 0x14, 0x14, 0x1F, 0x14, 0x14, 0x14, + 0x06, 0x08, 0x08, 0x1F, 0x08, 0x1F, 0x08, 0x08, 0x08, + 0x06, 0x08, 0x08, 0x08, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x08, + 0x06, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, + 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, + 0x06, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x06, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x16, 0x09, 0x09, 0x09, 0x16, 0x00, + 0x06, 0x00, 0x0E, 0x19, 0x0F, 0x19, 0x0F, 0x01, 0x00, + 0x06, 0x00, 0x1F, 0x19, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x06, 0x00, 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + 0x06, 0x1F, 0x11, 0x02, 0x04, 0x02, 0x11, 0x1F, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x09, 0x09, 0x09, 0x06, 0x00, + 0x06, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0x16, 0x03, 0x00, + 0x06, 0x00, 0x1F, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x06, 0x1F, 0x04, 0x0E, 0x11, 0x11, 0x0E, 0x04, 0x1F, + 0x06, 0x04, 0x0A, 0x11, 0x1F, 0x11, 0x0A, 0x04, 0x00, + 0x06, 0x04, 0x0A, 0x11, 0x11, 0x0A, 0x0A, 0x1B, 0x00, + 0x06, 0x0C, 0x02, 0x0C, 0x0E, 0x11, 0x11, 0x0E, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x15, 0x15, 0x0E, 0x00, + 0x06, 0x10, 0x0E, 0x19, 0x15, 0x15, 0x13, 0x0E, 0x01, + 0x06, 0x0E, 0x01, 0x01, 0x0F, 0x01, 0x01, 0x0E, 0x00, + 0x06, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x06, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, + 0x06, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x1F, 0x00, + 0x06, 0x02, 0x04, 0x08, 0x04, 0x02, 0x00, 0x1F, 0x00, + 0x06, 0x08, 0x04, 0x02, 0x04, 0x08, 0x00, 0x1F, 0x00, + 0x06, 0x1C, 0x14, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x07, + 0x06, 0x0C, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x0C, 0x00, + 0x06, 0x00, 0x17, 0x1D, 0x00, 0x17, 0x1D, 0x00, 0x00, + 0x06, 0x0E, 0x1B, 0x1B, 0x0E, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x1C, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x04, + 0x06, 0x0E, 0x12, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, + 0x06, 0x0E, 0x18, 0x0C, 0x06, 0x1E, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + diff --git a/sys/include/fonts/topaz.h b/sys/include/fonts/topaz.h new file mode 100644 index 0000000..c2f576c --- /dev/null +++ b/sys/include/fonts/topaz.h @@ -0,0 +1,2307 @@ +const unsigned char Topaz[] = { + 0x08, 0x01, 0x00, 0xFF, 1, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01111110, + 0b10000001, + 0b10100101, + 0b10000001, + 0b10111101, + 0b10011001, + 0b10000001, + 0b01111110, + 0x08, + 0b01111110, + 0b11111111, + 0b11011011, + 0b11111111, + 0b11000011, + 0b11100111, + 0b11111111, + 0b01111110, + 0x08, + 0b00110110, + 0b01111111, + 0b01111111, + 0b01111111, + 0b00111110, + 0b00011100, + 0b00001000, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00111110, + 0b01111111, + 0b00111110, + 0b00011100, + 0b00001000, + 0b00000000, + 0x08, + 0b00011100, + 0b00111110, + 0b00011100, + 0b01111111, + 0b01111111, + 0b01101011, + 0b00001000, + 0b00011100, + 0x08, + 0b00001000, + 0b00001000, + 0b00011100, + 0b00111110, + 0b01111111, + 0b00111110, + 0b00001000, + 0b00011100, + 0x08, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b11111111, + 0b11111111, + 0b11100111, + 0b11000011, + 0b11000011, + 0b11100111, + 0b11111111, + 0b11111111, + 0x08, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000010, + 0b01000010, + 0b01100110, + 0b00111100, + 0b00000000, + 0x08, + 0b11111111, + 0b11000011, + 0b10011001, + 0b10111101, + 0b10111101, + 0b10011001, + 0b11000011, + 0b11111111, + 0x08, + 0b11110000, + 0b11100000, + 0b11110000, + 0b10111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0x08, + 0b00111100, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b01111110, + 0b00011000, + 0x08, + 0b11111100, + 0b11001100, + 0b11111100, + 0b00001100, + 0b00001100, + 0b00001110, + 0b00001111, + 0b00000111, + 0x08, + 0b11111110, + 0b11000110, + 0b11111110, + 0b11000110, + 0b11000110, + 0b11100110, + 0b01100111, + 0b00000011, + 0x08, + 0b10011001, + 0b01011010, + 0b00111100, + 0b11100111, + 0b11100111, + 0b00111100, + 0b01011010, + 0b10011001, + 0x08, + 0b00000001, + 0b00000111, + 0b00011111, + 0b01111111, + 0b00011111, + 0b00000111, + 0b00000001, + 0b00000000, + 0x08, + 0b01000000, + 0b01110000, + 0b01111100, + 0b01111111, + 0b01111100, + 0b01110000, + 0b01000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0x08, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00000000, + 0b01100110, + 0b00000000, + 0x08, + 0b11111110, + 0b11011011, + 0b11011011, + 0b11011110, + 0b11011000, + 0b11011000, + 0b11011000, + 0b00000000, + 0x08, + 0b01111110, + 0b11000011, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00110001, + 0b00011111, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111110, + 0b01111110, + 0b01111110, + 0b00000000, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0b11111111, + 0x08, + 0b00011000, + 0b00111100, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00111100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00110000, + 0b01111111, + 0b00110000, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00001100, + 0b00000110, + 0b01111111, + 0b00000110, + 0b00001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00100100, + 0b01100110, + 0b11111111, + 0b01100110, + 0b00100100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00111100, + 0b01111110, + 0b11111111, + 0b11111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b11111111, + 0b11111111, + 0b01111110, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00011110, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000000, + 0x08, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00000000, + 0x08, + 0b00001100, + 0b00111110, + 0b00000011, + 0b00011110, + 0b00110000, + 0b00011111, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b01100011, + 0b00110011, + 0b00011000, + 0b00001100, + 0b01100110, + 0b01100011, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00011100, + 0b01101110, + 0b00111011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000110, + 0b00000110, + 0b00000011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0x08, + 0b00000000, + 0b01100110, + 0b00111100, + 0b11111111, + 0b00111100, + 0b01100110, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00000110, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000001, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00111011, + 0b00111111, + 0b00110111, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00001100, + 0b00001111, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011100, + 0b00000110, + 0b00110011, + 0b00111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011100, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110000, + 0b00110000, + 0b00000000, + 0x08, + 0b00111111, + 0b00000011, + 0b00011111, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011100, + 0b00000110, + 0b00000011, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111111, + 0b00110011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011000, + 0b00001110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00000110, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000000, + 0x08, + 0b00111110, + 0b01100011, + 0b01111011, + 0b01111011, + 0b01111011, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b00111111, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01100110, + 0b00111100, + 0b00000000, + 0x08, + 0b00111111, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00111111, + 0b00000000, + 0x08, + 0b01111111, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b01000110, + 0b01111111, + 0b00000000, + 0x08, + 0b01111111, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b00000011, + 0b00000011, + 0b01110011, + 0b01100110, + 0b01111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b01111000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b01100111, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0x08, + 0b01100011, + 0b01110111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b01100011, + 0b01100111, + 0b01101111, + 0b01111011, + 0b01110011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111011, + 0b00011110, + 0b00111000, + 0b00000000, + 0x08, + 0b00111111, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00011110, + 0b00110110, + 0b01100111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000111, + 0b00011100, + 0b00111000, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111111, + 0b00101101, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00000000, + 0x08, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111111, + 0b01110111, + 0b01100011, + 0b00000000, + 0x08, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b01111111, + 0b00110011, + 0b00011001, + 0b00001100, + 0b01000110, + 0b01100011, + 0b01111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00011110, + 0b00000000, + 0x08, + 0b00000011, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b01000000, + 0b00000000, + 0x08, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011110, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0x08, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111101, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00111000, + 0b00110000, + 0b00110000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00000110, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011111, + 0x08, + 0b00000111, + 0b00000110, + 0b00110110, + 0b01101110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00011000, + 0b00000000, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00001110, + 0x08, + 0b00000111, + 0b00000110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00110110, + 0b01100111, + 0b00000000, + 0x08, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00001111, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b01111000, + 0x08, + 0b00000000, + 0b00000000, + 0b00011011, + 0b00110110, + 0b00110110, + 0b00000110, + 0b00001111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111110, + 0b00000011, + 0b00011110, + 0b00110000, + 0b00011111, + 0b00000000, + 0x08, + 0b00001000, + 0b00001100, + 0b00111110, + 0b00001100, + 0b00001100, + 0b00101100, + 0b00011000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111111, + 0b00110110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00011111, + 0x08, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00011001, + 0b00001100, + 0b00100110, + 0b00111111, + 0b00000000, + 0x08, + 0b00111000, + 0b00001100, + 0b00001100, + 0b00000111, + 0b00001100, + 0b00001100, + 0b00111000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00000111, + 0b00001100, + 0b00001100, + 0b00111000, + 0b00001100, + 0b00001100, + 0b00000111, + 0b00000000, + 0x08, + 0b01101110, + 0b00111011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00011000, + 0b00110000, + 0b00011110, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b01111110, + 0b11000011, + 0b00111100, + 0b01100000, + 0b01111100, + 0b01100110, + 0b11111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111110, + 0b00000011, + 0b00000011, + 0b00111110, + 0b01100000, + 0b00111100, + 0x08, + 0b01111110, + 0b11000011, + 0b00111100, + 0b01100110, + 0b01111110, + 0b00000110, + 0b00111100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00000011, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00111110, + 0b01100011, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0x08, + 0b00000111, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00110011, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00111111, + 0b00110011, + 0b00000000, + 0x08, + 0b00111000, + 0b00000000, + 0b00111111, + 0b00000110, + 0b00011110, + 0b00000110, + 0b00111111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111110, + 0b00110000, + 0b11111110, + 0b00110011, + 0b11111110, + 0b00000000, + 0x08, + 0b01111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110011, + 0b00110011, + 0b01110011, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000111, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000111, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00111111, + 0b00110000, + 0b00011111, + 0x08, + 0b01100011, + 0b00011100, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00011100, + 0b00000000, + 0x08, + 0b00110011, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00000011, + 0b00000011, + 0b01111110, + 0b00011000, + 0b00011000, + 0x08, + 0b00011100, + 0b00110110, + 0b00100110, + 0b00001111, + 0b00000110, + 0b01100111, + 0b00111111, + 0b00000000, + 0x08, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00111111, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00000000, + 0x08, + 0b00001111, + 0b00011011, + 0b00011011, + 0b00101111, + 0b00110011, + 0b01111011, + 0b00110011, + 0b01110000, + 0x08, + 0b01110000, + 0b11011000, + 0b00011000, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00001110, + 0x08, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00011100, + 0b00000000, + 0b00001110, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00111000, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00111000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01111110, + 0b00000000, + 0x08, + 0b00000000, + 0b00011111, + 0b00000000, + 0b00011111, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111111, + 0b00000000, + 0b00110011, + 0b00110111, + 0b00111111, + 0b00111011, + 0b00110011, + 0b00000000, + 0x08, + 0b00111100, + 0b00110110, + 0b00110110, + 0b01111100, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b00111100, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00000000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00000011, + 0b00000011, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111111, + 0b00110000, + 0b00110000, + 0b00000000, + 0b00000000, + 0x08, + 0b01100011, + 0b00110011, + 0b00011011, + 0b01111100, + 0b11000110, + 0b01110011, + 0b00011001, + 0b11111000, + 0x08, + 0b01100011, + 0b00110011, + 0b00011011, + 0b11001111, + 0b11100110, + 0b11110011, + 0b11111001, + 0b11000000, + 0x08, + 0b00000000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00011000, + 0x08, + 0b00000000, + 0b11001100, + 0b01100110, + 0b00110011, + 0b01100110, + 0b11001100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00110011, + 0b01100110, + 0b11001100, + 0b01100110, + 0b00110011, + 0b00000000, + 0b00000000, + 0x08, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0b01000100, + 0b00010001, + 0x08, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0b10101010, + 0b01010101, + 0x08, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0b00111011, + 0b01101110, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01100000, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100000, + 0b01101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101111, + 0b01100000, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00011000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101100, + 0b00001100, + 0b11111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111100, + 0b00001100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b11101100, + 0b00001100, + 0b11101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b11101111, + 0b00000000, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00011000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111100, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b01101100, + 0b01101100, + 0b01101100, + 0b01101100, + 0b11101111, + 0b01101100, + 0b01101100, + 0b01101100, + 0x08, + 0b00011000, + 0b00011000, + 0b11111111, + 0b00000000, + 0b11111111, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0x08, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0b00001111, + 0x08, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0b11110000, + 0x08, + 0b11111111, + 0b11111111, + 0b11111111, + 0b11111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00010011, + 0b00111011, + 0b01101110, + 0b00000000, + 0x08, + 0b00000000, + 0b00011110, + 0b00110011, + 0b00011111, + 0b00110011, + 0b00011111, + 0b00000011, + 0b00000011, + 0x08, + 0b00000000, + 0b01111111, + 0b01100011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000000, + 0x08, + 0b00000000, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0x08, + 0b01111111, + 0b01100110, + 0b00001100, + 0b00011000, + 0b00001100, + 0b01100110, + 0b01111111, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000011, + 0x08, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0x08, + 0b00111111, + 0b00001100, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00001100, + 0b00111111, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01111111, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00110110, + 0b01110111, + 0b00000000, + 0x08, + 0b00111000, + 0b00001100, + 0b00011000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b01111110, + 0b11011011, + 0b11011011, + 0b01111110, + 0b00000000, + 0b00000000, + 0x08, + 0b01100000, + 0b00110000, + 0b01111110, + 0b11011011, + 0b11011011, + 0b01111110, + 0b00000110, + 0b00000011, + 0x08, + 0b00111100, + 0b00000110, + 0b00000011, + 0b00111111, + 0b00000011, + 0b00000110, + 0b00111100, + 0b00000000, + 0x08, + 0b00011110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00000000, + 0x08, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00000000, + 0x08, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00111111, + 0b00000000, + 0x08, + 0b01110000, + 0b11011000, + 0b11011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0x08, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011011, + 0b00011011, + 0b00001110, + 0x08, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00111111, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00000000, + 0x08, + 0b00000000, + 0b01001110, + 0b00111001, + 0b00000000, + 0b01001110, + 0b00111001, + 0b00000000, + 0b00000000, + 0x08, + 0b00011100, + 0b00110110, + 0b00110110, + 0b00011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b11110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110111, + 0b00110110, + 0b00111100, + 0b00111000, + 0x08, + 0b00011110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00011110, + 0b00110000, + 0b00011100, + 0b00000110, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00000000, + 0b00000000, + 0x08, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +}; diff --git a/sys/include/fonts/vga.h b/sys/include/fonts/vga.h new file mode 100644 index 0000000..afa0a10 --- /dev/null +++ b/sys/include/fonts/vga.h @@ -0,0 +1,1833 @@ +static const unsigned char vga[] = { + + 16, // lpc + 1, // bpl + 32, // start + 0x7f, // end + 1, // bpp + +// 32 $20 'space' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 33 $21 'exclam' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00111100, + 0b00111100, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 34 $22 'quotedbl' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00100100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 35 $23 'numbersign' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00110110, + 0b01111111, + 0b00110110, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 36 $24 'dollar' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00011000, + 0b00011000, + 0b00111110, + 0b01100011, + 0b01000011, + 0b00000011, + 0b00111110, + 0b01100000, + 0b01100000, + 0b01100001, + 0b01100011, + 0b00111110, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, +// 37 $25 'percent' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000011, + 0b01100011, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01100011, + 0b01100001, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 38 $26 'ampersand' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b00110110, + 0b00011100, + 0b01101110, + 0b00111011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 39 $27 'quotesingle' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00000100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 40 $28 'parenleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 41 $29 'parenright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001100, + 0b00011000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 42 $2a 'asterisk' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100110, + 0b00111100, + 0b11111111, + 0b00111100, + 0b01100110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 43 $2b 'plus' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 44 $2c 'comma' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, +// 45 $2d 'hyphen' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 46 $2e 'period' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 47 $2f 'slash' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01000000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b00000001, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 48 $30 'zero' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 49 $31 'one' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011100, + 0b00011110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 50 $32 'two' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 51 $33 'three' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100000, + 0b01100000, + 0b00111100, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 52 $34 'four' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00110000, + 0b00111000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b01111111, + 0b00110000, + 0b00110000, + 0b00110000, + 0b01111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 53 $35 'five' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00111111, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 54 $36 'six' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00000110, + 0b00000011, + 0b00000011, + 0b00111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 55 $37 'seven' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100011, + 0b01100000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 56 $38 'eight' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 57 $39 'nine' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111110, + 0b01100000, + 0b01100000, + 0b01100000, + 0b00110000, + 0b00011110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 58 $3a 'colon' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 59 $3b 'semicolon' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00001100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 60 $3c 'less' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 61 $3d 'equal' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b01111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 62 $3e 'greater' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000110, + 0b00001100, + 0b00011000, + 0b00110000, + 0b01100000, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 63 $3f 'question' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 64 $40 'at' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01111011, + 0b01111011, + 0b01111011, + 0b00111011, + 0b00000011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 65 $41 'A' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 66 $42 'B' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 67 $43 'C' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01000011, + 0b01100110, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 68 $44 'D' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011111, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00011111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 69 $45 'E' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100110, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 70 $46 'F' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100110, + 0b01000110, + 0b00010110, + 0b00011110, + 0b00010110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 71 $47 'G' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b01100110, + 0b01000011, + 0b00000011, + 0b00000011, + 0b01111011, + 0b01100011, + 0b01100011, + 0b01100110, + 0b01011100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 72 $48 'H' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 73 $49 'I' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 74 $4a 'J' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00011110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 75 $4b 'K' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100111, + 0b01100110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 76 $4c 'L' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b01000110, + 0b01100110, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 77 $4d 'M' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01110111, + 0b01111111, + 0b01111111, + 0b01101011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 78 $4e 'N' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100111, + 0b01101111, + 0b01111111, + 0b01111011, + 0b01110011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 79 $4f 'O' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 80 $50 'P' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 81 $51 'Q' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01111011, + 0b00111110, + 0b00110000, + 0b01110000, + 0b00000000, + 0b00000000, +// 82 $52 'R' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111111, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 83 $53 'S' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b00000110, + 0b00011100, + 0b00110000, + 0b01100000, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 84 $54 'T' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111110, + 0b01111110, + 0b01011010, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 85 $55 'U' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 86 $56 'V' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00001000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 87 $57 'W' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01111111, + 0b01110111, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 88 $58 '1' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b00110110, + 0b00111110, + 0b00011100, + 0b00011100, + 0b00111110, + 0b00110110, + 0b01100011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 89 $59 'Y' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 90 $5a 'Z' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01111111, + 0b01100011, + 0b01100001, + 0b00110000, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01000011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 91 $5b 'bracketleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 92 $5c 'backslash' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000001, + 0b00000011, + 0b00000111, + 0b00001110, + 0b00011100, + 0b00111000, + 0b01110000, + 0b01100000, + 0b01000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 93 $5d 'bracketright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111100, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00110000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 94 $5e 'asciicircum' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 95 $5f 'underscore' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b11111111, + 0b00000000, + 0b00000000, +// 96 $60 'grave' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00001100, + 0b00001100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 97 $61 'a' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00011110, + 0b00110000, + 0b00111110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 98 $62 'b' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 99 $63 'c' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b00000011, + 0b00000011, + 0b00000011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 100 $64 'd' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00111000, + 0b00110000, + 0b00110000, + 0b00111100, + 0b00110110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 101 $65 'e' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01111111, + 0b00000011, + 0b00000011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 102 $66 'f' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00110110, + 0b00100110, + 0b00000110, + 0b00001111, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 103 $67 'g' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00110011, + 0b00011110, + 0b00000000, +// 104 $68 'h' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b00110110, + 0b01101110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 105 $69 'i' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 106 $6a 'j' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01100000, + 0b01100000, + 0b00000000, + 0b01110000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100000, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00000000, +// 107 $6b 'k' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000111, + 0b00000110, + 0b00000110, + 0b01100110, + 0b00110110, + 0b00011110, + 0b00011110, + 0b00110110, + 0b01100110, + 0b01100111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 108 $6c 'l' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011100, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00111100, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 109 $6d 'm' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110111, + 0b01111111, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 110 $6e 'n' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 111 $6f 'o' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 112 $70 'p' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, +// 113 $71 'q' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00111110, + 0b00110000, + 0b00110000, + 0b01111000, + 0b00000000, +// 114 $72 'r' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111011, + 0b01101110, + 0b01100110, + 0b00000110, + 0b00000110, + 0b00000110, + 0b00001111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 115 $73 's' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00111110, + 0b01100011, + 0b00000110, + 0b00011100, + 0b00110000, + 0b01100011, + 0b00111110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 116 $74 't' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00001100, + 0b00001100, + 0b00111111, + 0b00001100, + 0b00001100, + 0b00001100, + 0b00001100, + 0b01101100, + 0b00111000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 117 $75 'u' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b00110011, + 0b01101110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 118 $76 'v' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b01100110, + 0b00111100, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 119 $77 'w' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01101011, + 0b01101011, + 0b01101011, + 0b01111111, + 0b00110110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 120 $78 'x' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b00110110, + 0b00011100, + 0b00011100, + 0b00011100, + 0b00110110, + 0b01100011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 121 $79 'y' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111110, + 0b01100000, + 0b00110000, + 0b00011111, + 0b00000000, +// 122 $7a 'z' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b01111111, + 0b00110011, + 0b00011000, + 0b00001100, + 0b00000110, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 123 $7b 'braceleft' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01110000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 124 $7c 'bar' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 125 $7d 'braceright' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00001110, + 0b00011000, + 0b00011000, + 0b00011000, + 0b01110000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00011000, + 0b00001110, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 126 $7e 'asciitilde' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b01101110, + 0b00111011, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +// 127 $7f 'char127' +// width 8, bbx 0, bby -4, bbw 8, bbh 16 + 8, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00001000, + 0b00011100, + 0b00110110, + 0b01100011, + 0b01100011, + 0b01100011, + 0b01111111, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, + 0b00000000, +}; diff --git a/sys/include/hx8357.h b/sys/include/hx8357.h new file mode 100644 index 0000000..9562826 --- /dev/null +++ b/sys/include/hx8357.h @@ -0,0 +1,21 @@ +#ifndef _HX8356_H +#define _HX8357_H + +#include "tty.h" + +extern const struct devspec hx8357devs[]; +extern int hx8357_open(dev_t dev, int flag, int mode); +extern int hx8357_close(dev_t dev, int flag, int mode); +extern int hx8357_read(dev_t dev, struct uio *uio, int flag); +extern int hx8357_write(dev_t dev, struct uio *uio, int flag); +extern int hx8357_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag); +extern int hx8357_select(dev_t dev, int rw); +extern void hx8357_putc(dev_t dev, char c); +extern char hx8357_getc(dev_t dev); +extern void hx8357_init(); + + +extern struct tty hx8357_ttys[1]; + + +#endif diff --git a/sys/pic32/cfg/hxtft.dev b/sys/pic32/cfg/hxtft.dev new file mode 100644 index 0000000..15fc01f --- /dev/null +++ b/sys/pic32/cfg/hxtft.dev @@ -0,0 +1,4 @@ +always + file hx8357.o + define HX8357_ENABLED +end always diff --git a/sys/pic32/devsw.c b/sys/pic32/devsw.c index 45a511e..769bb52 100644 --- a/sys/pic32/devsw.c +++ b/sys/pic32/devsw.c @@ -54,6 +54,10 @@ extern int strcmp(char *s1, char *s2); #include "pty.h" #endif +#ifdef HX8357_ENABLED +#include "hx8357.h" +#endif + /* * Null routine; placed in insignificant entries * in the bdevsw and cdevsw tables. @@ -239,6 +243,14 @@ const struct cdevsw cdevsw[] = { }, #endif +#ifdef HX8357_ENABLED +{ + hx8357_open, hx8357_close, hx8357_read, hx8357_write, + hx8357_ioctl, nulldev, hx8357_ttys, hx8357_select, + nostrategy, hx8357_getc, hx8357_putc, hx8357devs +}, +#endif + // End the list with a blank entry { 0, 0, 0, 0, diff --git a/sys/pic32/hx8357.c b/sys/pic32/hx8357.c new file mode 100644 index 0000000..5934a33 --- /dev/null +++ b/sys/pic32/hx8357.c @@ -0,0 +1,774 @@ +/* + * HX8357 TFT driver for PIC32. + * + * Copyright (C) 2014 Majenko Technologies + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ + +#include "param.h" +#include "conf.h" +#include "user.h" +#include "ioctl.h" +#include "systm.h" +#include "uio.h" +#include "adc.h" +#include "debug.h" +#include "hx8357.h" + +#include "fonts/default.h" + +char frame[40][80]; + +typedef struct { + unsigned char linesPerCharacter; + unsigned char bytesPerLine; + unsigned char startGlyph; + unsigned char endGlyph; + unsigned char bitsPerPixel; +} FontHeader; + + +struct tty hx8357_ttys[1]; + +typedef struct { + union { + unsigned short value; + struct { + unsigned r:5; + unsigned g:6; + unsigned b:5; + } __attribute__((packed)); + } __attribute__((packed)); +} __attribute__((packed)) Color565; + + +#define HX8357_EXIT_SLEEP_MODE 0x11 +#define HX8357_SET_DISPLAY_OFF 0x28 +#define HX8357_SET_DISPLAY_ON 0x29 +#define HX8357_SET_COLUMN_ADDRESS 0x2A +#define HX8357_SET_PAGE_ADDRESS 0x2B +#define HX8357_WRITE_MEMORY_START 0x2C +#define HX8357_READ_MEMORY_START 0x2E +#define HX8357_SET_TEAR_ON 0x35 +#define HX8357_SET_ADDRESS_MODE 0x36 +#define HX8357_SET_PIXEL_FORMAT 0x3A +#define HX8357_WRITE_MEMORY_CONTINUE 0x3C +#define HX8357_READ_MEMORY_CONTINUE 0x3E +#define HX8357_SET_INTERNAL_OSCILLATOR 0xB0 +#define HX8357_SET_POWER_CONTROL 0xB1 +#define HX8357_SET_DISPLAY_MODE 0xB4 +#define HX8357_SET_VCOM_VOLTAGE 0xB6 +#define HX8357_ENABLE_EXTENSION_COMMAND 0xB9 +#define HX8357_SET_PANEL_DRIVING 0xC0 // not documented! +#define HX8357_SET_PANEL_CHARACTERISTIC 0xCC +#define HX8357_SET_GAMMA_CURVE 0xE0 + +static int _width = 320; +static int _height = 480; + +static int cursor_x = 0; +static int cursor_y = 0; + +static int rotation = 0; + +static unsigned short textcolor = 0x7BEF; +static unsigned short texthicolor = 0xFFFF; +static unsigned short textbgcolor = 0x0000; + +const unsigned char *font = Default; +const unsigned char _font_width = 6; +const unsigned char _font_height = 8; + +const struct devspec hx8357devs[] = { + { 0, "tft0" }, + { 1, "tftin0" }, + { 0, 0 } +}; + +void inline static writeCommand(unsigned short c) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0000; + PMDIN = c; +} + +void inline static writeData(unsigned short c) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + PMDIN = c; +} + +void initDisplay() { + PMCONCLR = PIC32_PMCON_ON; + asm volatile("nop"); + + PMCONSET = PIC32_PMCON_PTWREN | PIC32_PMCON_PTRDEN; + PMCONCLR = PIC32_PMCON_CSF; + PMAEN = 0x0001; // Enable PMA0 pin for RS pin and CS1 as CS + PMMODE = PIC32_PMMODE_MODE16 | PIC32_PMMODE_MODE_MAST2; + PMADDR = 0; + PMCONSET = PIC32_PMCON_ON; + + + writeCommand(HX8357_EXIT_SLEEP_MODE); //Sleep Out + udelay(150000); + writeCommand(HX8357_ENABLE_EXTENSION_COMMAND); + writeData(0xFF); + writeData(0x83); + writeData(0x57); + udelay(1000); + writeCommand(HX8357_SET_POWER_CONTROL); + writeData(0x00); + writeData(0x12); + writeData(0x12); + writeData(0x12); + writeData(0xC3); + writeData(0x44); + udelay(1000); + writeCommand(HX8357_SET_DISPLAY_MODE); + writeData(0x02); + writeData(0x40); + writeData(0x00); + writeData(0x2A); + writeData(0x2A); + writeData(0x20); + writeData(0x91); + udelay(1000); + writeCommand(HX8357_SET_VCOM_VOLTAGE); + writeData(0x38); + udelay(1000); + writeCommand(HX8357_SET_INTERNAL_OSCILLATOR); + writeData(0x68); + writeCommand(0xE3); //Unknown Command + writeData(0x2F); + writeData(0x1F); + writeCommand(0xB5); //Set BGP + writeData(0x01); + writeData(0x01); + writeData(0x67); + writeCommand(HX8357_SET_PANEL_DRIVING); + writeData(0x70); + writeData(0x70); + writeData(0x01); + writeData(0x3C); + writeData(0xC8); + writeData(0x08); + udelay(1000); + writeCommand(0xC2); // Set Gate EQ + writeData(0x00); + writeData(0x08); + writeData(0x04); + udelay(1000); + writeCommand(HX8357_SET_PANEL_CHARACTERISTIC); + writeData(0x09); + udelay(1000); + writeCommand(HX8357_SET_GAMMA_CURVE); + writeData(0x01); + writeData(0x02); + writeData(0x03); + writeData(0x05); + writeData(0x0E); + writeData(0x22); + writeData(0x32); + writeData(0x3B); + writeData(0x5C); + writeData(0x54); + writeData(0x4C); + writeData(0x41); + writeData(0x3D); + writeData(0x37); + writeData(0x31); + writeData(0x21); + writeData(0x01); + writeData(0x02); + writeData(0x03); + writeData(0x05); + writeData(0x0E); + writeData(0x22); + writeData(0x32); + writeData(0x3B); + writeData(0x5C); + writeData(0x54); + writeData(0x4C); + writeData(0x41); + writeData(0x3D); + writeData(0x37); + writeData(0x31); + writeData(0x21); + writeData(0x00); + writeData(0x01); + udelay(1000); + writeCommand(HX8357_SET_PIXEL_FORMAT); //COLMOD RGB888 + writeData(0x55); + writeCommand(HX8357_SET_ADDRESS_MODE); + writeData(0x00); + writeCommand(HX8357_SET_TEAR_ON); //TE ON + writeData(0x00); + udelay(10000); + writeCommand(HX8357_SET_DISPLAY_ON); //Display On + udelay(10000); + writeCommand(HX8357_WRITE_MEMORY_START); //Write SRAM Data + int l, c; + for (l = 0; l < 39; l++) { + for (c = 0; c < 80; c++) { + frame[l][c]=' '; + } + } +} + +void inline static setAddrWindow(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1) { + writeCommand(HX8357_SET_COLUMN_ADDRESS); // Column addr set + writeData((x0) >> 8); + writeData(x0); // XSTART + writeData((x1) >> 8); + writeData(x1); // XEND + + writeCommand(HX8357_SET_PAGE_ADDRESS); // Row addr set + writeData((y0) >> 8); + writeData(y0); // YSTART + writeData((y1) >> 8); + writeData(y1); // YEND + + writeCommand(HX8357_WRITE_MEMORY_START); //Write SRAM Data +} + +void inline static setPixel(int x, int y, unsigned short color) { + if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) + return; + setAddrWindow(x,y,x+1,y+1); + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + PMDIN = color; +} + + +void inline static fillRectangle(int x, int y, int w, int h, unsigned short color) +{ + setAddrWindow(x, y, x+w-1, y+h-1); + + while (PMMODE & PIC32_PMMODE_BUSY); + PMADDR = 0x0001; + for(y=h; y>0; y--) { + for(x=w; x>0; x--) { + while (PMMODE & PIC32_PMMODE_BUSY); + PMDIN = color; + } + } +} + +void inline static setRotation(unsigned char m) +{ + writeCommand(HX8357_SET_ADDRESS_MODE); + rotation = m % 4; // can't be higher than 3 + switch (rotation) + { + case 0: + //PORTRAIT + writeData(0x0000); + _width = 320; + _height = 480; + break; + case 1: + //LANDSCAPE + writeData(0x0060); + _width = 480; + _height = 320; + break; + case 2: + //UPSIDE DOWN PORTRAIT + writeData(0x00C0); + _width = 320; + _height = 480; + break; + case 3: + //UPSIDE DOWN LANDSCAPE + writeData(0x00A0); + _width = 480; + _height = 320; + break; + } +} + +unsigned short inline static mix(unsigned short a, unsigned short b, unsigned char pct) { + Color565 col_a; + Color565 col_b; + Color565 col_out; + col_a.value = a; + col_b.value = b; + unsigned int temp; + temp = (((int)col_a.r * (255-pct)) / 255) + (((unsigned int)col_b.r * pct) / 255); + col_out.r = temp; + temp = (((int)col_a.g * (255-pct)) / 255) + (((unsigned int)col_b.g * pct) / 255); + col_out.g = temp; + temp = (((int)col_a.b * (255-pct)) / 255) + (((unsigned int)col_b.b * pct) / 255); + col_out.b = temp; + return col_out.value; +} + + +unsigned char drawChar(int x, int y, unsigned char c, unsigned short color, unsigned short bg) { + + if (font == NULL) { + return 0; + } + + FontHeader *header = (FontHeader *)font; + + if (c < header->startGlyph || c > header->endGlyph) { + return 0; + } + + c = c - header->startGlyph; + + // Start of this character's data is the character number multiplied by the + // number of lines in a character (plus one for the character width) multiplied + // by the number of bytes in a line, and then offset by 4 for the header. + unsigned int charstart = (c * ((header->linesPerCharacter * header->bytesPerLine) + 1)) + sizeof(FontHeader); // Start of character data + unsigned char charwidth = font[charstart++]; // The first byte of a block is the width of the character + + unsigned int bitmask = (1 << header->bitsPerPixel) - 1; + + setAddrWindow(x, y, x + charwidth - 1, y + header->linesPerCharacter - 1); + + char lineNumber = 0; + for (lineNumber = 0; lineNumber < header->linesPerCharacter; lineNumber++ ) { + unsigned char lineData = 0; + + char bitsLeft = -1; + unsigned char byteNumber = 0; + + char pixelNumber = 0; + for (pixelNumber = 0; pixelNumber < charwidth; pixelNumber++) { + if (bitsLeft <= 0) { + bitsLeft = 8; + lineData = font[charstart + (lineNumber * header->bytesPerLine) + (header->bytesPerLine - byteNumber - 1)]; + byteNumber++; + } + unsigned int pixelValue = lineData & bitmask; + if (pixelValue > 0) { + writeData(color); + } else { + writeData(bg); + } + lineData >>= header->bitsPerPixel; + bitsLeft -= header->bitsPerPixel; + } + } + return charwidth; +} + +void updateLine(int l) { + if (l < 0) return; + if (l > 39) return; + + int c; + for (c = 0; c < 80; c++) { + drawChar(c * _font_width, l * _font_height, frame[l][c] & 0x7F, frame[l][c] & 0x80 ? texthicolor : textcolor, textbgcolor); + } +} + +void scrollUp() { + int l, c; + for (l = 0; l < 39; l++) { + for (c = 0; c < 80; c++) { + frame[l][c] = frame[l+1][c]; + } + updateLine(l); + } + for (c = 0; c < 80; c++) { + frame[39][c] = ' '; + } + updateLine(39); +} + +int inEscape = 0; + +int edValPos = 0; +int edVal[4]; + +int bold = 0; + +void printChar(unsigned char c) { + switch (c) { + case '\n': + cursor_y ++; + if (cursor_y > 39) { + scrollUp(); + cursor_y = 39; + } + break; + case '\r': + cursor_x = 0; + break; + case 8: + cursor_x--; + if (cursor_x < 0) { + cursor_x = 79; + cursor_y--; + if (cursor_y < 0) { + cursor_y = 0; + } + } + break; + default: + frame[cursor_y][cursor_x] = c | (bold ? 0x80 : 0x00); + cursor_x++; + if (cursor_x == 80) { + cursor_x = 0; + cursor_y++; + if (cursor_y == 40) { + cursor_y = 39; + scrollUp(); + } + } + updateLine(cursor_y); + + } +} + +int extended = 0; + +void writeChar(unsigned char c) { + + int i, j; + updateLine(cursor_y); + + if (inEscape == 1) { + + switch (c) { + case 27: + inEscape = 0; + printChar('^'); + printChar('['); + break; + case '[': + extended = 1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + edVal[edValPos%4] *= 10; + edVal[edValPos%4] += c - '0'; + break; + case ';': + edValPos++; + edVal[edValPos%4] = 0; + break; + case 'J': + if (extended == 1) { + if (edVal[0] == 0) { + for (i = cursor_y; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } else if (edVal[0] == 1) { + for (i = 0; i < cursor_y; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } else if (edVal[0] == 2) { + for (i = 0; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } + } + } + inEscape = 0; + break; + case 'H': + if (extended == 1) { + if (edVal[0] == 0) { + edVal[0] = 1; + } + if (edVal[1] == 0) { + edVal[1] = 1; + } + cursor_x = (edVal[1] - 1) % 80; + cursor_y = (edVal[0] - 1) % 40; + } + inEscape = 0; + break; + case 'm': + if (extended == 1) { + if (edVal[0] == 0) { + bold = 0; + } else if (edVal[0] == 1) { + bold = 1; + } + } + inEscape = 0; + break; + + case 'A': + if (extended == 0) { + cursor_y--; + if (cursor_y > 0) { + cursor_y = 39; + } + } + inEscape = 0; + break; + + case 'B': + if (extended == 0) { + cursor_y++; + if (cursor_y == 40) { + cursor_y = 0; + } + } + inEscape = 0; + break; + + case 'C': + if (extended == 0) { + cursor_x++; + if (cursor_x == 80) { + cursor_x = 0; + cursor_y++; + if (cursor_y == 40) { + cursor_y = 0; + } + } + } + inEscape = 0; + break; + + case 'D': + if (extended == 0) { + cursor_x--; + if (cursor_x < 0) { + cursor_x = 79; + cursor_y--; + if (cursor_y < 0) { + cursor_y = 39; + } + } + } + inEscape = 0; + break; + + case 'K': + if (extended == 1) { + if (edVal[0] == 0) { + for (i = cursor_x; i < 80; i++) { + frame[cursor_y][i] = ' '; + } + } else if (edVal[1] == 1) { + for (i = 0; i < cursor_x; i++) { + frame[cursor_y][i] = ' '; + } + } else { + for (i = 0; i < 80; i++) { + frame[cursor_y][i] = ' '; + } + } + updateLine(cursor_y); + } + inEscape = 0; + break; + + default: + if (extended) { + printf("Unhandled extended escape code %c\n", c); + } else { + printf("Unhandled escape code %c\n", c); + } + inEscape = 0; + break; + } + + } else { + if (c == 27) { + inEscape = 1; + extended = 0; + edVal[0] = 0; + edValPos = 0; + } else { + printChar(c); + } + } + drawChar(cursor_x * _font_width, cursor_y * _font_height, frame[cursor_y][cursor_x] & 0x7F, 0x0000, bold ? texthicolor : textcolor); +// for (i = 0; i < _font_width; i++) { +// setPixel(cursor_x * _font_width + i, (cursor_y + 1) * _font_height - 1, 0xFFFF); +// } + +} + +void hx8357_start(struct tty *tp) { + register int s; + + s = spltty(); + ttyowake(tp); +// tp->t_state &= TS_BUSY; + if (tp->t_outq.c_cc > 0) { + led_control (LED_TTY, 1); + while (tp->t_outq.c_cc != 0) { + int c = getc (&tp->t_outq); + writeChar(c); + } + led_control (LED_TTY, 0); + } +// tp->t_state |= TS_BUSY; + splx (s); +} + +void hx8357_init() { + initDisplay(); + setRotation(1); + int i,j; + for (i = 0; i < 40; i++) { + for (j = 0; j < 80; j++) { + frame[i][j] = ' '; + } + updateLine(i); + } +} + +int ttyIsOpen = 0; + +int hx8357_open(dev_t dev, int flag, int mode) { + int unit = minor(dev); + + if (unit == 0) { + ttyIsOpen = 1; + struct tty *tp = &hx8357_ttys[0]; + tp->t_oproc = hx8357_start; + tp->t_state = TS_ISOPEN | TS_CARR_ON; + tp->t_flags = ECHO | XTABS | CRMOD | CRTBS | CRTERA | CTLECH | CRTKIL; + return ttyopen(dev, tp); + } + if (unit == 1) { + if (!ttyIsOpen) { + return EIO; + } + return 0; + } + return ENODEV; +} + +int hx8357_close(dev_t dev, int flag, int mode) { + int unit = minor(dev); + + if (unit == 0) { + ttyIsOpen = 0; + struct tty *tp = &hx8357_ttys[0]; + ttyclose(tp); + return 0; + } + + if (unit == 1) { + return 0; + } + return ENODEV; +} + +int hx8357_read(dev_t dev, struct uio *uio, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + return ttread(tp, uio, flag); + } + if (unit == 1) { + return EIO; + } + + return ENODEV; +} + +int hx8357_write(dev_t dev, struct uio *uio, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[0]; + return ttwrite(tp, uio, flag); + } + + if (unit == 1) { + if (!ttyIsOpen) { + return EIO; + } + struct tty *tp = &hx8357_ttys[0]; + struct iovec *iov = uio->uio_iov; + + while (iov->iov_len > 0) { + ttyinput(*(iov->iov_base), tp); + iov->iov_base ++; + iov->iov_len --; + uio->uio_resid --; + uio->uio_offset ++; + } + return 0; + } + return ENODEV; +} + +int hx8357_ioctl(dev_t dev, register u_int cmd, caddr_t addr, int flag) { + int unit = minor(dev); + + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + int error; + + error = ttioctl(tp, cmd, addr, flag); + if (error < 0) + error = ENOTTY; + return (error); + } + if (unit == 1) { + return EIO; + } + + return ENODEV; + +} + +void hx8357_putc(dev_t dev, char c) { + writeChar(c); +} + +char hx8357_getc(dev_t dev) { + return 0; +} + +int hx8357_select (dev_t dev, int rw) { + int unit = minor(dev); + if (unit == 0) { + struct tty *tp = &hx8357_ttys[unit]; + return (ttyselect (tp, rw)); + } + if (unit == 1) { + return EIO; + } + return ENODEV; +} + diff --git a/sys/pic32/machdep.c b/sys/pic32/machdep.c index bf4cf1e..7ccea87 100644 --- a/sys/pic32/machdep.c +++ b/sys/pic32/machdep.c @@ -27,6 +27,10 @@ # include #endif +#ifdef HX8357_ENABLED +#include "hx8357.h" +#endif + #ifdef POWER_ENABLED extern void power_init(); extern void power_off(); @@ -344,6 +348,9 @@ startup() #endif #ifdef UARTUSB_ENABLED usbinit(); +#endif +#ifdef HX8357_ENABLED + hx8357_init(); #endif cninit(); diff --git a/sys/pic32/picadillo_rambo/Makefile b/sys/pic32/picadillo_rambo/Makefile index e7bddc7..a37cfa6 100644 --- a/sys/pic32/picadillo_rambo/Makefile +++ b/sys/pic32/picadillo_rambo/Makefile @@ -6,13 +6,13 @@ S = ../../../tools/configsys/../../sys/kernel vpath %.c $(M):$(S) vpath %.S $(M):$(S) -KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_spirams.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o +KERNOBJ += adc.o clock.o cons.o devsw.o exception.o exec_aout.o exec_conf.o exec_elf.o exec_script.o exec_subr.o gpio.o hx8357.o init_main.o init_sysent.o kern_clock.o kern_descrip.o kern_exec.o kern_exit.o kern_fork.o kern_mman.o kern_proc.o kern_prot.o kern_prot2.o kern_resource.o kern_sig.o kern_sig2.o kern_subr.o kern_synch.o kern_sysctl.o kern_time.o machdep.o mem.o rd_sd.o rd_spirams.o rdisk.o signal.o spi_bus.o startup.o subr_prf.o subr_rmap.o swap.o sys_generic.o sys_inode.o sys_pipe.o sys_process.o syscalls.o sysctl.o tty.o tty_subr.o tty_tty.o uart.o ufs_alloc.o ufs_bio.o ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_mount.o ufs_namei.o ufs_subr.o ufs_syscalls.o ufs_syscalls2.o vers.o vfs_vnops.o vm_sched.o vm_swap.o vm_swp.o EXTRA_TARGETS = DEFS += -DADC_ENABLED=YES DEFS += -DBUS_DIV=1 DEFS += -DBUS_KHZ=80000 -DEFS += -DCONSOLE_DEVICE=tty0 +DEFS += -DCONSOLE_DEVICE=tft0 DEFS += -DCPU_IDIV=2 DEFS += -DCPU_KHZ=80000 DEFS += -DCPU_MUL=20 @@ -46,13 +46,14 @@ DEFS += -DEXEC_AOUT DEFS += -DEXEC_ELF DEFS += -DEXEC_SCRIPT DEFS += -DGPIO_ENABLED=YES +DEFS += -DHX8357_ENABLED DEFS += -DKERNEL -DEFS += -DPARTITION="spirams0:sa@1500" +DEFS += -DPARTITION="spirams0:sa@2040" DEFS += -DPIC32MX7 DEFS += -DSD0_CS_PIN=9 DEFS += -DSD0_CS_PORT=TRISG DEFS += -DSD0_PORT=2 -DEFS += -DSPIRAMS_CHIPS=13 +DEFS += -DSPIRAMS_CHIPS=16 DEFS += -DSPIRAMS_CHIPSIZE=128 DEFS += -DSPIRAMS_CS0_PIN=0 DEFS += -DSPIRAMS_CS0_PORT=TRISA @@ -62,6 +63,12 @@ DEFS += -DSPIRAMS_CS11_PIN=7 DEFS += -DSPIRAMS_CS11_PORT=TRISA DEFS += -DSPIRAMS_CS12_PIN=14 DEFS += -DSPIRAMS_CS12_PORT=TRISG +DEFS += -DSPIRAMS_CS13_PIN=12 +DEFS += -DSPIRAMS_CS13_PORT=TRISG +DEFS += -DSPIRAMS_CS14_PIN=13 +DEFS += -DSPIRAMS_CS14_PORT=TRISG +DEFS += -DSPIRAMS_CS15_PIN=5 +DEFS += -DSPIRAMS_CS15_PORT=TRISF DEFS += -DSPIRAMS_CS1_PIN=1 DEFS += -DSPIRAMS_CS1_PORT=TRISA DEFS += -DSPIRAMS_CS2_PIN=4 diff --git a/sys/pic32/picadillo_rambo/PICADILLO_RAMBO b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO index 415c6d8..9e8dd20 100644 --- a/sys/pic32/picadillo_rambo/PICADILLO_RAMBO +++ b/sys/pic32/picadillo_rambo/PICADILLO_RAMBO @@ -8,15 +8,16 @@ linker bootloader-max32 device kernel cpu_khz=80000 bus_khz=80000 -device console device=tty0 +device console device=tft0 device uart1 baud=115200 device rdisk device sd0 port=2 cs=48 -device spirams0 port=4 chips=13 cs0=26 cs1=27 cs2=28 cs3=29 cs4=30 cs5=31 cs6=32 cs7=33 cs8=34 cs9=35 cs10=36 cs11=37 cs12=38 +device spirams0 port=4 chips=16 cs0=26 cs1=27 cs2=28 cs3=29 cs4=30 cs5=31 cs6=32 cs7=33 cs8=34 cs9=35 cs10=36 cs11=37 cs12=38 cs13=39 cs14=40 cs15=51 -option PARTITION=spirams0:sa@1500 +option PARTITION=spirams0:sa@2040 +device hxtft device gpio device adc device foreignbootloader diff --git a/sys/pic32/rd_spirams.c b/sys/pic32/rd_spirams.c new file mode 100644 index 0000000..531080b --- /dev/null +++ b/sys/pic32/rd_spirams.c @@ -0,0 +1,438 @@ +#include "param.h" +#include "systm.h" +#include "buf.h" +#include "errno.h" +#include "dk.h" +#include "rdisk.h" +#include "spi_bus.h" + +#include "debug.h" + +#define SPIRAM_WREN 0x06 +#define SPIRAM_WRDI 0x04 +#define SPIRAM_RDSR 0x05 +#define SPIRAM_WRSR 0x01 +#define SPIRAM_READ 0x03 +#define SPIRAM_WRITE 0x02 +#define SPIRAM_SLEEP 0xB9 +#define SPIRAM_WAKE 0xAB + +#ifndef SPIRAMS_MHZ +#define SPIRAMS_MHZ 10 +#endif + +int fd[SPIRAMS_CHIPS]; + +int spirams_size(int unit) +{ + return SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE; +} + +#define MRBSIZE 1024 +#define MRBLOG2 10 + +unsigned int spir_read_block(unsigned int chip, unsigned int address, unsigned int length, char *data) +{ + register unsigned int cs = 0; + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + TRIS_CLR(SPIRAMS_LED0_PORT) = 1<>16); + spi_transfer(fd[chip], address>>8); + spi_transfer(fd[chip], address); + + // If the length is a multiple of 32 bits, then do a 32 bit transfer +/* + if((length & 0x03) == 0) + spi_bulk_read_32(fd[chip],length,data); + else if((length & 0x01) == 0) + spi_bulk_read_16(fd[chip],length,data); + else +*/ + spi_bulk_read(fd[chip],length,(unsigned char *)data); + + spi_deselect(fd[chip]); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + LAT_CLR(SPIRAMS_LED0_PORT) = 1< 0) + { + pass++; + toread = bcount; + if(toread > MRBSIZE) + toread = MRBSIZE; + + chip = offset / SPIRAMS_CHIPSIZE; + + address = (offset<<10) - (chip * (SPIRAMS_CHIPSIZE*1024)); + + + if(chip>=SPIRAMS_CHIPS) + { + printf("!!!EIO\n"); + return EIO; + } + spir_read_block(chip, address, toread, data); + bcount -= toread; + offset += (toread>>MRBLOG2); + data += toread; + } + return 1; +} + +unsigned int spir_write_block(unsigned int chip, unsigned int address, unsigned int length, char *data) +{ + register unsigned int cs = 0; + char blank __attribute__((unused)); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + TRIS_CLR(SPIRAMS_LED0_PORT) = 1<>16); + spi_transfer(fd[chip], address>>8); + spi_transfer(fd[chip], address); + +/* + if((length & 0x03) == 0) + spi_bulk_write_32(fd[chip],length,data); + else if((length & 0x01) == 0) + spi_bulk_write_16(fd[chip],length,data); + else +*/ + spi_bulk_write(fd[chip],length,(unsigned char *)data); + + spi_deselect(fd[chip]); + + switch(chip) + { + case 0: + #ifdef SPIRAMS_LED0_PORT + LAT_CLR(SPIRAMS_LED0_PORT) = 1< 0) + { + pass++; + towrite = bcount; + if(towrite > MRBSIZE) + towrite = MRBSIZE; + + chip = offset / SPIRAMS_CHIPSIZE; + address = (offset<<10) - (chip * (SPIRAMS_CHIPSIZE*MRBSIZE)); + + if(chip>=SPIRAMS_CHIPS) + { + printf("!!!EIO\n"); + return EIO; + } + + spir_write_block(chip, address, towrite, data); + bcount -= towrite; + offset += (towrite>>MRBLOG2); + data += towrite; + } + return 1; +} + +void spirams_preinit (int unit) +{ + struct buf *bp; + + if (unit >= 1) + return; + + /* Initialize hardware. */ + + + fd[0] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS0_PORT,SPIRAMS_CS0_PIN); + if(fd[0]==-1) return; + + spi_brg(fd[0],SPIRAMS_MHZ * 1000); + spi_set(fd[0],PIC32_SPICON_CKE); + +#ifdef SPIRAMS_CS1_PORT + fd[1] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS1_PORT,SPIRAMS_CS1_PIN); + + spi_brg(fd[1],SPIRAMS_MHZ * 1000); + spi_set(fd[1],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS2_PORT + fd[2] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS2_PORT,SPIRAMS_CS2_PIN); + + spi_brg(fd[2],SPIRAMS_MHZ * 1000); + spi_set(fd[2],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS3_PORT + fd[3] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS3_PORT,SPIRAMS_CS3_PIN); + + spi_brg(fd[3],SPIRAMS_MHZ * 1000); + spi_set(fd[3],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS4_PORT + fd[4] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS4_PORT,SPIRAMS_CS4_PIN); + + spi_brg(fd[4],SPIRAMS_MHZ * 1000); + spi_set(fd[4],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS5_PORT + fd[5] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS5_PORT,SPIRAMS_CS5_PIN); + + spi_brg(fd[5],SPIRAMS_MHZ * 1000); + spi_set(fd[5],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS6_PORT + fd[6] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS6_PORT,SPIRAMS_CS6_PIN); + + spi_brg(fd[6],SPIRAMS_MHZ * 1000); + spi_set(fd[6],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS7_PORT + fd[7] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS7_PORT,SPIRAMS_CS7_PIN); + + spi_brg(fd[7],SPIRAMS_MHZ * 1000); + spi_set(fd[7],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS8_PORT + fd[8] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS8_PORT,SPIRAMS_CS8_PIN); + + spi_brg(fd[8],SPIRAMS_MHZ * 1000); + spi_set(fd[8],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS9_PORT + fd[9] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS9_PORT,SPIRAMS_CS9_PIN); + + spi_brg(fd[9],SPIRAMS_MHZ * 1000); + spi_set(fd[9],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS10_PORT + fd[10] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS10_PORT,SPIRAMS_CS10_PIN); + + spi_brg(fd[10],SPIRAMS_MHZ * 1000); + spi_set(fd[10],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS11_PORT + fd[11] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS11_PORT,SPIRAMS_CS11_PIN); + + spi_brg(fd[11],SPIRAMS_MHZ * 1000); + spi_set(fd[11],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS12_PORT + fd[12] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS12_PORT,SPIRAMS_CS12_PIN); + + spi_brg(fd[12],SPIRAMS_MHZ * 1000); + spi_set(fd[12],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS13_PORT + fd[13] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS13_PORT,SPIRAMS_CS13_PIN); + + spi_brg(fd[13],SPIRAMS_MHZ * 1000); + spi_set(fd[13],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS14_PORT + fd[14] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS14_PORT,SPIRAMS_CS14_PIN); + + spi_brg(fd[14],SPIRAMS_MHZ * 1000); + spi_set(fd[14],PIC32_SPICON_CKE); +#endif +#ifdef SPIRAMS_CS15_PORT + fd[15] = spi_open(SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS15_PORT,SPIRAMS_CS15_PIN); + + spi_brg(fd[15],SPIRAMS_MHZ * 1000); + spi_set(fd[15],PIC32_SPICON_CKE); +#endif + + printf("spirams0: port %d %s, size %dKB, speed %d Mbit/sec\n", + SPIRAMS_PORT, spi_name(fd[0]),SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE, + spi_get_brg(fd[0]) / 1000); + bp = prepartition_device("spirams0"); + if(bp) + { + spirams_write (0, 0, bp->b_addr, 512); + brelse(bp); + } +} From 8d55f87ab855194d7a72eaf2ce6f2ebba5facab7 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Thu, 4 Sep 2014 19:29:18 -0700 Subject: [PATCH 40/40] Fsutil: dynamically allocate data structure for file i/o. --- tools/fsutil/mount.c | 108 +++++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/tools/fsutil/mount.c b/tools/fsutil/mount.c index fb4b256..489e84d 100644 --- a/tools/fsutil/mount.c +++ b/tools/fsutil/mount.c @@ -35,12 +35,6 @@ extern int verbose; -/* - * File descriptor to be used by op_open(), op_create(), op_read(), - * op_write(), op_release(), op_fgetattr(), op_fsync(), op_ftruncate(). - */ -static fs_file_t file; - /* * Print a message to log file. */ @@ -128,16 +122,18 @@ int op_getattr(const char *path, struct stat *statbuf) */ int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_fgetattr(path=\"%s\", statbuf=%p, fi=%p)\n", path, statbuf, fi); if (strcmp(path, "/") == 0) return op_getattr(path, statbuf); - if (file.inode.mode == 0) + if (! fh) return -EBADF; - return getstat (&file.inode, statbuf); + return getstat (&fh->inode, statbuf); } /* @@ -151,20 +147,30 @@ int op_open(const char *path, struct fuse_file_info *fi) printlog("--- op_open(path=\"%s\", fi=%p) flags=%#x \n", path, fi, fi->flags); - if (! fs_file_open (fs, &file, path, write_flag)) { + fs_file_t *fh = calloc (1, sizeof(fs_file_t)); + if (! fh) { + printlog("--- out of memory\n"); + return -ENOMEM; + } + + if (! fs_file_open (fs, fh, path, write_flag)) { printlog("--- open failed\n"); + free (fh); + fi->fh = 0; return -ENOENT; } - if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + if ((fh->inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { /* Cannot open special files. */ - file.inode.mode = 0; + free (fh); + fi->fh = 0; return -ENXIO; } if (fi->flags & O_APPEND) { - file.offset = file.inode.size; + fh->offset = fh->inode.size; } + fi->fh = (intptr_t) fh; return 0; } @@ -178,16 +184,27 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) printlog("--- op_create(path=\"%s\", mode=0%03o, fi=%p)\n", path, mode, fi); - file.inode.mode = 0; - if (! fs_file_create (fs, &file, path, mode & 07777)) { + fs_file_t *fh = calloc (1, sizeof(fs_file_t)); + if (! fh) { + printlog("--- out of memory\n"); + return -ENOMEM; + } + + if (! fs_file_create (fs, fh, path, mode & 07777)) { printlog("--- create failed\n"); - if ((file.inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) + if ((fh->inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + free (fh); + fi->fh = 0; return -EISDIR; + } + free (fh); + fi->fh = 0; return -EIO; } - file.inode.mtime = time(0); - file.inode.dirty = 1; - fs_file_close (&file); + fh->inode.mtime = time(0); + fh->inode.dirty = 1; + fs_file_close (fh); + fi->fh = (intptr_t) fh; return 0; } @@ -196,17 +213,19 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi) */ int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_read(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", path, buf, size, offset, fi); - if (offset >= file.inode.size) + if (offset >= fh->inode.size) return 0; - file.offset = offset; - if (size > file.inode.size - offset) - size = file.inode.size - offset; + fh->offset = offset; + if (size > fh->inode.size - offset) + size = fh->inode.size - offset; - if (! fs_file_read (&file, (unsigned char*) buf, size)) { + if (! fs_file_read (fh, (unsigned char*) buf, size)) { printlog("--- read failed\n"); return -EIO; } @@ -220,16 +239,18 @@ int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_ int op_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_write(path=\"%s\", buf=%p, size=%d, offset=%lld, fi=%p)\n", path, buf, size, offset, fi); - file.offset = offset; - if (! fs_file_write (&file, (unsigned char*) buf, size)) { + fh->offset = offset; + if (! fs_file_write (fh, (unsigned char*) buf, size)) { printlog("--- read failed\n"); return -EIO; } - file.inode.mtime = time(0); - file.inode.dirty = 1; + fh->inode.mtime = time(0); + fh->inode.dirty = 1; return size; } @@ -238,13 +259,16 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset, */ int op_release(const char *path, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_release(path=\"%s\", fi=%p)\n", path, fi); - if (file.inode.mode == 0) + if (! fh) return -EBADF; - fs_file_close (&file); - file.inode.mode = 0; + fs_file_close (fh); + free (fh); + fi->fh = 0; return 0; } @@ -269,7 +293,7 @@ int op_truncate(const char *path, off_t newsize) } fs_inode_truncate (&f.inode, newsize); f.inode.mtime = time(0); - file.inode.dirty = 1; + f.inode.dirty = 1; fs_file_close (&f); return 0; } @@ -279,20 +303,22 @@ int op_truncate(const char *path, off_t newsize) */ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_ftruncate(path=\"%s\", offset=%lld, fi=%p)\n", path, offset, fi); - if (! file.writable) + if (! fh->writable) return -EACCES; - if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { + if ((fh->inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) { /* Cannot truncate special files. */ return -EINVAL; } - fs_inode_truncate (&file.inode, offset); - file.inode.mtime = time(0); - file.inode.dirty = 1; - fs_file_close (&file); + fs_inode_truncate (&fh->inode, offset); + fh->inode.mtime = time(0); + fh->inode.dirty = 1; + fs_file_close (fh); return 0; } @@ -311,7 +337,7 @@ int op_unlink(const char *path) printlog("--- search failed\n"); return -ENOENT; } - if ((file.inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { + if ((inode.mode & INODE_MODE_FMT) == INODE_MODE_FDIR) { /* Cannot unlink directories. */ return -EISDIR; } @@ -724,11 +750,13 @@ int op_flush(const char *path, struct fuse_file_info *fi) */ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi) { + fs_file_t *fh = (fs_file_t*) (intptr_t) fi->fh; + printlog("--- op_fsync(path=\"%s\", datasync=%d, fi=%p)\n", path, datasync, fi); - if (datasync == 0 && file.writable) { - if (! fs_inode_save (&file.inode, 0)) + if (datasync == 0 && fh->writable) { + if (! fs_inode_save (&fh->inode, 0)) return -EIO; } return 0;