/* parse a mailbox style header */ int parse_header(char *line, String *sender, String *date) { if (!IS_HEADER(line)) return -1; line += sizeof("From ") - 1; s_restart(sender); while(*line==' '||*line=='\t') line++; if(*line == '"'){ s_putc(sender, *line++); while(*line && *line != '"') s_putc(sender, *line++); s_putc(sender, *line++); } else { while(*line && *line != ' ' && *line != '\t') s_putc(sender, *line++); } s_terminate(sender); s_restart(date); while(*line==' '||*line=='\t') line++; while(*line) s_putc(date, *line++); s_terminate(date); return 0; }
/* * Get the next token from `line'. The symbol `\l' is replaced by * the name of the local system. */ extern String * rule_parse(String *line, char *system, int *backl) { String *token; String *expanded; char *cp; token = s_parse(line, 0); if(token == 0) return(token); if(strchr(s_to_c(token), '\\')==0) return(token); expanded = s_new(); for(cp = s_to_c(token); *cp; cp++) { if(*cp == '\\') switch(*++cp) { case 'l': s_append(expanded, system); *backl = 1; break; case '\\': s_putc(expanded, '\\'); break; default: s_putc(expanded, '\\'); s_putc(expanded, *cp); break; } else s_putc(expanded, *cp); } s_free(token); s_terminate(expanded); return(expanded); }
/* Get the next field from a String. The field is delimited by white space, * single or double quotes. */ String * s_parse(String *from, String *to) { if (*from->ptr == '\0') return 0; if (to == 0) to = s_new(); if (*from->ptr == '\'') { from->ptr++; for (;*from->ptr != '\'' && *from->ptr != '\0'; from->ptr++) s_putc(to, *from->ptr); if (*from->ptr == '\'') from->ptr++; } else if (*from->ptr == '"') { from->ptr++; for (;*from->ptr != '"' && *from->ptr != '\0'; from->ptr++) s_putc(to, *from->ptr); if (*from->ptr == '"') from->ptr++; } else { for (;!isspace(*from->ptr) && *from->ptr != '\0'; from->ptr++) s_putc(to, *from->ptr); } s_terminate(to); /* crunch trailing white */ while(isspace(*from->ptr)) from->ptr++; return to; }
/* * simplify an address, reduce to a domain */ static String* simplify(char *addr) { int dots, dotlim; char *p, *at; String *s; mklower(addr); at = strchr(addr, '@'); if(at == nil){ /* local address, make it an exact match */ s = s_copy("="); s_append(s, addr); return s; } /* copy up to, and including, the '@' sign */ at++; s = s_copy("~"); for(p = addr; p < at; p++){ if(strchr(".*+?(|)\\[]^$", *p)) s_putc(s, '\\'); s_putc(s, *p); } /* * just any address matching the two most significant domain elements, * except for .uk, which needs three. */ s_append(s, "(.*\\.)?"); p = addr+strlen(addr); /* point at NUL */ if (p[-1] == '.') *--p = '\0'; if (p - addr > 3 && strcmp(".uk", p - 3) == 0) dotlim = 3; else dotlim = 2; dots = 0; while(--p > at) if(*p == '.' && ++dots >= dotlim){ p++; break; } for(; *p; p++){ if(strchr(".*+?(|)\\[]^$", *p) != nil) s_putc(s, '\\'); s_putc(s, *p); } s_terminate(s); return s; }
static void xtoa(unsigned long x, const unsigned long *dp) { char c; unsigned long d; if(x) { while(x < *dp) ++dp; do { d = *dp++; c = '0'; while(x >= d) ++c, x -= d; s_putc(c); } while(!(d & 1)); } else s_putc('0'); }
uint16_t s_printf(char *instr, const char *format, ...) { char c; int i; long n; sptr = instr; slen = 0; sptr[slen] = '\0'; va_list a; va_start(a, format); while( (c = *format++) ) { if(c == '%') { switch(c = *format++) { case 's': // String s_puts(va_arg(a, char*)); break; case 'c': // Char s_putc(va_arg(a, int)); // Char gets promoted to Int in args, so it's an int we're looking for (GCC warning) break; case 'i': // 16 bit Integer case 'd': // 16 bit Integer case 'u': // 16 bit Unsigned i = va_arg(a, int); if( (c == 'i' || c == 'd') && i < 0 ) i = -i, s_putc('-'); xtoa((unsigned)i, dv + 5); break; case 'l': // 32 bit Long case 'n': // 32 bit uNsigned loNg n = va_arg(a, long); if(c == 'l' && n < 0) n = -n, s_putc('-'); xtoa((unsigned long)n, dv); break; case 'x': // 16 bit heXadecimal i = va_arg(a, int); puth(i >> 12); puth(i >> 8); puth(i >> 4); puth(i); break; case 0: return slen; default: goto bad_fmt; } } else bad_fmt: s_putc(c); }
/* * simplify an address, reduce to a domain */ static String* simplify(char *addr) { int dots; char *p, *at; String *s; mklower(addr); at = strchr(addr, '@'); if(at == nil){ /* local address, make it an exact match */ s = s_copy("="); s_append(s, addr); return s; } /* copy up to the '@' sign */ at++; s = s_copy("~"); for(p = addr; p < at; p++){ if(strchr(".*+?(|)\\[]^$", *p)) s_putc(s, '\\'); s_putc(s, *p); } /* just any address matching the two most significant domain elements */ s_append(s, "(.*\\.)?"); p = addr+strlen(addr); dots = 0; for(; p > at; p--){ if(*p != '.') continue; if(dots++ > 0){ p++; break; } } for(; *p; p++){ if(strchr(".*+?(|)\\[]^$", *p) != 0) s_putc(s, '\\'); s_putc(s, *p); } s_terminate(s); return s; }
/* Append an input line to a String. * * Empty lines and leading whitespace are removed. */ static char * rdline(Biobuf *fp, String *to) { int c; int len = 0; c = Bgetc(fp); /* eat leading white */ while(c==' ' || c=='\t' || c=='\n' || c=='\r') c = Bgetc(fp); if(c < 0) return 0; for(;;){ switch(c) { case -1: goto out; case '\\': c = Bgetc(fp); if (c != '\n') { s_putc(to, '\\'); s_putc(to, c); len += 2; } break; case '\r': break; case '\n': if(len != 0) goto out; break; default: s_putc(to, c); len++; break; } c = Bgetc(fp); } out: s_terminate(to); return to->ptr - len; }
void escape(String *s, char c) { /* * a-zA-Z0-9: pass * space(' '): '+' * other: %XX */ char buf[4]; if (c == ' ') s_putc(s, '+'); else if (isalnum(c)) s_putc(s, c); else { sprint(buf, "%%%02x", (uchar) c); s_append(s, buf); } }
/* * get a line that ends in crnl or cr, turn terminating crnl into a nl * * return 0 on EOF */ static int getcrnl(String *s, Biobuf *fp) { int c; for(;;){ c = Bgetc(fp); if(debug) { seek(2, 0, 2); fprint(2, "%c", c); } switch(c){ case 0: break; case -1: goto out; case '\r': c = Bgetc(fp); if(c == '\n'){ if(debug) { seek(2, 0, 2); fprint(2, "%c", c); stamp(); } s_putc(s, '\n'); goto out; } Bungetc(fp); s_putc(s, '\r'); break; case '\n': s_putc(s, c); goto out; default: s_putc(s, c); break; } } out: s_terminate(s); return s_len(s); }
/* append a char array to a String */ String * s_append(String *to, char *from) { if (to == 0) to = s_new(); if (from == 0) return to; for(; *from; from++) s_putc(to, *from); s_terminate(to); return to; }
/* * Get a line including a crnl into a string. Convert crnl into nl. */ char * getcrnl(String *s) { int c; int count; count = 0; for(;;){ c = Bgetc(&bin); if(debug) Bputc(&berr, c); switch(c){ case -1: s_append(s, "connection closed unexpectedly by remote system"); s_terminate(s); return 0; case '\r': c = Bgetc(&bin); if(c == '\n'){ case '\n': s_putc(s, c); if(debug) Bputc(&berr, c); count++; s_terminate(s); return s->ptr - count; } Bungetc(&bin); s_putc(s, '\r'); if(debug) Bputc(&berr, '\r'); count++; break; default: s_putc(s, c); count++; break; } } }
PT(ssd1306_printf,uint8_t row, uint8_t col, __code const char * format, ...) { va_list args; PT_B PT_LOCK(busy); va_start(args,format); i=0; printf_tiny(format,args); va_end(args); sbuf[16]=0; //force trancation PT_CALL(ssd1306_move,row,col); i=0; while(sbuf[i] != 0) { s_putc(sbuf[i++]); PT_CALL(ssd1306_tile,buf,9); } PT_UNLOCK(busy); PT_E }
static int rreadstr(char *delim, char *s) /* if s != 0, skip this chars before reading */ { int c; s_reset(sbuf); if(s) skip(s); while((c=GETC()) >= 0){ if(strchr(delim, c)){ UNGETC(c); s_terminate(sbuf); return Tstring; } s_putc(sbuf, c); } if(c == Beof) yyerror("eof in string"); return Terror; }
/* get the text of a header line minus the field name */ static String* getstring(Node *p) { String *s; s = s_new(); if(p == nil) return s; for(p = p->next; p; p = p->next){ if(p->s){ s_append(s, s_to_c(p->s)); }else{ s_putc(s, p->c); s_terminate(s); } if(p->white) s_append(s, s_to_c(p->white)); } return s; }
static int readname(char *s) { int c; s_reset(sbuf); if(s) skip(s); while((c=GETC()) >= 0 && (isalnum(c) || c == '-')) s_putc(sbuf, c); if(c == Beof){ yyerror("eof in id/class"); return Terror; } UNGETC(c); if(s_len(sbuf) == 0){ yyerror("empty name"); return Terror; } s_terminate(sbuf); return Tstring; }
char * convert(Rune *s) { static String *sbuf; int i, n, state; char buf[JISmax]; if (sbuf == nil) { sbuf = s_new(); if (sbuf == nil) sysfatal("s_new: %r"); } state = 0; s_reset(sbuf); for ( ; *s; s++) { switch (chset) { case EUC_JP: n = runetoujis(buf, s); break; case ISO_2022_JP: n = runetojis(buf, s, &state); break; case Shift_JIS: n = runetosjis(buf, s); break; default: n = runetochar(buf, s); break; } for (i = 0; i < n; i++) escape(sbuf, buf[i]); } s_putc(sbuf, '\0'); return estrdup(s_to_c(sbuf)); }
int yylex(void) { int c, r; char c1; Sym *s; genblock: if(block != nblock){ if(block > nblock){ if(debug) fprint(2, "%s %d -> %d\n", ty(Tend), block, nblock); block--; return Tend; }else{ if(debug) fprint(2, "%s %d -> %d\n", ty(Tbegin), block, nblock); block++; return Tbegin; } } c = GETC(); if(c == Beof){ nblock = 0; if(block != nblock) goto genblock; return 0; } UNGETC(c); switch(state){ case Head0: /* [%type] string */ c = GETC(); if(c != '%'){ UNGETC(c); setstate(Body0); goto genblock; } r = readname(" \t"); if(r == Terror) return fail(Head2); s = lookup(s_to_c(sbuf)); yylval.sym = s; if(debug) fprint(2, "Sym[%s] %s\n", ty(s->type), s->name); setstate(Head1); return s->type; case Head1: /* %type [string] */ r = readstr("\n", " \t", 0); if(r == Terror) return fail(Head2); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); setstate(Head2); return Tstring; case Head2: skip(" \t"); c = GETC(); assert(c == '\n' || c == Beof); setstate(Head0); return ';'; case Body0: /* [indent] cmd inline */ c = GETC(); if(c == '%'){ UNGETC(c); setstate(Head0); goto genblock; } UNGETC(c); r = skip(" \t"); c = GETC(); if(c == '\n'){ if(debug) fprint(2, "%s\n", ty(Tbreak)); return Tbreak; } UNGETC(c); nblock = r; setstate(Body1); goto genblock; case Body1: /* indent [cmd] inline */ switch(c = GETC()){ case Beof: yyerror("eof in body"); if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); case '=': case '\\': case '+': case '*': case ':': case '-': case '>': if(debug) fprint(2, "%c\n", c); setstate(Body2); return c; case '!': if(debug) fprint(2, "%c\n", c); setstate(Code); return c; case '{': case '}': if(debug) fprint(2, "%c\n", c); setstate(Body3); return c; case '#': if(debug) fprint(2, "%c\n", c); setstate(ID); return c; case '.': if(debug) fprint(2, "%c\n", c); setstate(Class); return c; case '|': if(debug) fprint(2, "%c\n", c); setstate(Table); return c; default: UNGETC(c); if(debug) fprint(2, "\\\n"); setstate(Body2); return '\\'; } case Body2: /* indent cmd [inline] */ case Table: r = skip(" \t"); if(state == Table && r > 0) return ','; switch(c = getcc(&c1, "*[]|<>")){ case Beof: yyerror("eof in body"); if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); case '\n': UNGETC(c); setstate(Body3); break; case '*': case '[': case ']': case '|': case '<': case '>': if(c == '[' || c == '|' || c == '<') skip(" \t\n"); if(debug) fprint(2, "%c\n", c); return c; default: s_reset(sbuf); s_putc(sbuf, c1); while((c=getcc(&c1, "*[]|<>")) == 0){ if(state == Table && c1 == '\t'){ UNGETC(c); break; } s_putc(sbuf, c1); } s_terminate(sbuf); if(c > 0) UNGETC(c); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; } case Body3: skip(" \t"); c = GETC(); if(c != '\n') return fail(Body3); setstate(Body0); return ';'; case Code: r = readstr("\n", "", 1); if(r == Terror){ if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); } setstate(Body3); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; case ID: case Class: r = readname(" \t"); if(r == Terror){ if(debug) fprint(2, "%s\n", ty(Terror)); return fail(Body3); } setstate(Body3); yylval.s = estrdup(s_to_c(sbuf)); if(debug) fprint(2, "%s %q\n", ty(Tstring), yylval.s); return Tstring; default: assert(0); return Terror; } }
static void puth(unsigned n) { static const char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; s_putc(hex[n & 15]); }
/* fix 822 addresses */ static void rfc822cruft(message *mp) { Field *f; Node *p; String *body, *s; char *cp; /* * parse headers in in-core part */ yyinit(s_to_c(mp->body), s_len(mp->body)); mp->rfc822headers = 0; yyparse(); mp->rfc822headers = 1; mp->received = received; /* * remove equivalent systems in all addresses */ body = s_new(); cp = s_to_c(mp->body); for(f = firstfield; f; f = f->next){ if(f->node->c == MIMEVERSION) mp->havemime = 1; if(f->node->c == FROM) mp->havefrom = getaddr(f->node); if(f->node->c == SENDER) mp->havesender = getaddr(f->node); if(f->node->c == REPLY_TO) mp->havereplyto = getaddr(f->node); if(f->node->c == TO) mp->haveto = 1; if(f->node->c == DATE) mp->havedate = 1; if(f->node->c == SUBJECT) mp->havesubject = getstring(f->node); if(f->node->c == PRECEDENCE && f->node->next && f->node->next->next){ s = f->node->next->next->s; if(s && (strcmp(s_to_c(s), "bulk") == 0 || strcmp(s_to_c(s), "Bulk") == 0)) mp->bulk = 1; } for(p = f->node; p; p = p->next){ if(p->s){ if(p->addr){ cp = skipequiv(s_to_c(p->s)); s_append(body, cp); } else s_append(body, s_to_c(p->s)); }else{ s_putc(body, p->c); s_terminate(body); } if(p->white) s_append(body, s_to_c(p->white)); cp = p->end+1; } s_append(body, "\n"); } if(*s_to_c(body) == 0){ s_free(body); return; } if(*cp != '\n') s_append(body, "\n"); s_memappend(body, cp, s_len(mp->body) - (cp - s_to_c(mp->body))); s_terminate(body); firstfield = 0; mp->size += s_len(body) - s_len(mp->body); s_free(mp->body); mp->body = body; }
static String * substitute(String *source, Resub *subexp, message *mp) { int i; char *s; char *sp; String *stp; if(source == 0) return 0; sp = s_to_c(source); /* someplace to put it */ stp = s_new(); /* do the substitution */ while (*sp != '\0') { if(*sp == '\\') { switch (*++sp) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': i = *sp-'0'; if(subexp[i].s.sp != 0) for (s = subexp[i].s.sp; s < subexp[i].e.ep; s++) s_putc(stp, *s); break; case '\\': s_putc(stp, '\\'); break; case '\0': sp--; break; case 's': for(s = s_to_c(mp->replyaddr); *s; s++) s_putc(stp, *s); break; case 'p': if(mp->bulk) s = "bulk"; else s = "normal"; for(;*s; s++) s_putc(stp, *s); break; default: s_putc(stp, *sp); break; } } else if(*sp == '&') { if(subexp[0].s.sp != 0) for (s = subexp[0].s.sp; s < subexp[0].e.ep; s++) s_putc(stp, *s); } else if(*sp == '$') { sp = getrcvar(sp+1, &s); s_append(stp, s); free(s); sp--; /* counter sp++ below */ } else s_putc(stp, *sp); sp++; } s_terminate(stp); return s_restart(stp); }