#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93";
#endif
__RCSID("$NetBSD: map.c,v 1.13 2011/09/06 18:34:12 joerg Exp $");
#endif
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <term.h>
#include <termios.h>
#include "extern.h"
static int baudrate(char *);
#define GT 0x01
#define EQ 0x02
#define LT 0x04
#define NOT 0x08
#define GE (GT | EQ)
#define LE (LT | EQ)
typedef struct map {
struct map *next;
const char *porttype;
const char *type;
int conditional;
int speed;
} MAP;
static MAP *cur, *maplist;
void
add_mapping(const char *port, char *arg)
{
MAP *mapp;
char *copy, *p, *termp;
copy = strdup(arg);
mapp = malloc((u_int)sizeof(MAP));
if (copy == NULL || mapp == NULL)
err(1, "malloc");
mapp->next = NULL;
if (maplist == NULL)
cur = maplist = mapp;
else {
cur->next = mapp;
cur = mapp;
}
mapp->porttype = arg;
mapp->conditional = 0;
arg = strpbrk(arg, "><@=!:");
if (arg == NULL) {
mapp->type = mapp->porttype;
mapp->porttype = NULL;
goto done;
}
if (arg == mapp->porttype)
mapp->porttype = termp = NULL;
else
termp = arg;
for (;; ++arg)
switch(*arg) {
case '<':
if (mapp->conditional & GT)
goto badmopt;
mapp->conditional |= LT;
break;
case '>':
if (mapp->conditional & LT)
goto badmopt;
mapp->conditional |= GT;
break;
case '@':
case '=':
mapp->conditional |= EQ;
break;
case '!':
mapp->conditional |= NOT;
break;
default:
goto next;
}
next: if (*arg == ':') {
if (mapp->conditional)
goto badmopt;
++arg;
} else {
arg = strchr(p = arg, ':');
if (arg == NULL)
goto badmopt;
*arg++ = '\0';
mapp->speed = baudrate(p);
}
if (*arg == '\0')
goto badmopt;
mapp->type = arg;
if (termp != NULL)
*termp = '\0';
if (mapp->conditional & NOT)
mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
done: if (port) {
if (mapp->porttype)
badmopt: errx(1, "illegal -m option format: %s", copy);
mapp->porttype = port;
}
#ifdef MAPDEBUG
(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
(void)printf("type: %s\n", mapp->type);
(void)printf("conditional: ");
p = "";
if (mapp->conditional & GT) {
(void)printf("GT");
p = "/";
}
if (mapp->conditional & EQ) {
(void)printf("%sEQ", p);
p = "/";
}
if (mapp->conditional & LT)
(void)printf("%sLT", p);
(void)printf("\nspeed: %d\n", mapp->speed);
#endif
free(copy);
}
const char *
mapped(const char *type)
{
MAP *mapp;
int match;
match = 0;
for (mapp = maplist; mapp; mapp = mapp->next)
if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) {
switch (mapp->conditional) {
case 0:
match = 1;
break;
case EQ:
match = (ospeed == mapp->speed);
break;
case GE:
match = (ospeed >= mapp->speed);
break;
case GT:
match = (ospeed > mapp->speed);
break;
case LE:
match = (ospeed <= mapp->speed);
break;
case LT:
match = (ospeed < mapp->speed);
break;
}
if (match)
return (mapp->type);
}
return (type);
}
static int
baudrate(char *rate)
{
if (*rate == 'B')
++rate;
return (atoi(rate));
}