text: #if defined(_WIN32) && !defined(__CYGWIN__)
  /* Avoid confusing windows w/o cygwin w/ cygwin */
  #define LOSE32
  #endif
  
  #ifndef LOSE32
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <termios.h>
  #include <unistd.h>
  #include <errno.h>
  #include <fcntl.h>
  #include <stdlib.h>
  #include <string.h>
  #include <ctype.h>
  #include <sys/time.h>
  #include <stdio.h>
  #ifdef __CYGWIN__
  #include <windows.h>
  #include <io.h>
  #else
  #include <stdint.h>
  #endif
  #endif
  
  #ifdef LOSE32
  #include <windows.h>
  #include <stdint.h>
  #endif
  
  /* C implementation of the mote serial protocol. See
     net.tinyos.packet.Packetizer for more details */
  
  #undef DEBUG
  
  #include "serialsource.h"
  #include "serialprotocol.h"
  
  typedef int bool;
  
  enum {
  #ifndef __CYGWIN__
  #ifndef LOSE32
    FALSE = 0,
    TRUE = 1,
  #endif
  #endif
    BUFSIZE = 256,
    MTU = 256,
    ACK_TIMEOUT = 100000, /* in us */
    SYNC_BYTE = SERIAL_HDLC_FLAG_BYTE,
    ESCAPE_BYTE = SERIAL_HDLC_CTLESC_BYTE,
  
    P_ACK = SERIAL_SERIAL_PROTO_ACK,
    P_PACKET_ACK = SERIAL_SERIAL_PROTO_PACKET_ACK,
    P_PACKET_NO_ACK = SERIAL_SERIAL_PROTO_PACKET_NOACK,
    P_UNKNOWN = SERIAL_SERIAL_PROTO_PACKET_UNKNOWN
  };
  
  struct packet_list
  {
    uint8_t *packet;
    int len;
    struct packet_list *next;
  };
  
  struct serial_source_t {
  #ifndef LOSE32
    int fd;
  #else
    HANDLE hComm;
  #endif
    bool non_blocking;
    void (*message)(serial_source_msg problem);
  
    /* Receive state */
    struct {
      uint8_t buffer[BUFSIZE];
      int bufpos, bufused;
      uint8_t packet[MTU];
      bool in_sync, escaped;
      int count;
      struct packet_list *queue[256]; // indexed by protocol
    } recv;
    struct {
      uint8_t seqno;
      uint8_t *escaped;
      int escapeptr;
      uint16_t crc;
    } send;
  };
  
  #ifndef LOSE32
  static tcflag_t parse_baudrate(int requested)
  {
    int baudrate;
  
    switch (requested)
      {
  #ifdef B50
      case 50: baudrate = B50; break;
  #endif
  #ifdef B75
      case 75: baudrate = B75; break;
  #endif
  #ifdef B110
      case 110: baudrate = B110; break;
  #endif
  #ifdef B134
      case 134: baudrate = B134; break;
  #endif
  #ifdef B150
      case 150: baudrate = B150; break;
  #endif
  #ifdef B200
      case 200: baudrate = B200; break;
  #endif
  #ifdef B300
      case 300: baudrate = B300; break;
  #endif
  #ifdef B600
      case 600: baudrate = B600; break;
  #endif
  #ifdef B1200
      case 1200: baudrate = B1200; break;
  #endif
  #ifdef B1800
      case 1800: baudrate = B1800; break;
  #endif
  #ifdef B2400
      case 2400: baudrate = B2400; break;
  #endif
  #ifdef B4800
      case 4800: baudrate = B4800; break;
  #endif
  #ifdef B9600
      case 9600: baudrate = B9600; break;
  #endif
  #ifdef B19200
      case 19200: baudrate = B19200; break;
  #endif
  #ifdef B38400
      case 38400: baudrate = B38400; break;
  #endif
  #ifdef B57600
      case 57600: baudrate = B57600; break;
  #endif
  #ifdef B115200
      case 115200: baudrate = B115200; break;
  #endif
  #ifdef B230400
      case 230400: baudrate = B230400; break;
  #endif
  #ifdef B460800
      case 460800: baudrate = B460800; break;
  #endif
  #ifdef B500000
      case 500000: baudrate = B500000; break;
  #endif
  #ifdef B576000
      case 576000: baudrate = B576000; break;
  #endif
  #ifdef B921600
      case 921600: baudrate = B921600; break;
  #endif
  #ifdef B1000000
      case 1000000: baudrate = B1000000; break;
  #endif
  #ifdef B1152000
      case 1152000: baudrate = B1152000; break;
  #endif
  #ifdef B1500000
      case 1500000: baudrate = B1500000; break;
  #endif
  #ifdef B2000000
      case 2000000: baudrate = B2000000; break;
  #endif
  #ifdef B2500000
      case 2500000: baudrate = B2500000; break;
  #endif
  #ifdef B3000000
      case 3000000: baudrate = B3000000; break;
  #endif
  #ifdef B3500000
      case 3500000: baudrate = B3500000; break;
  #endif
  #ifdef B4000000
      case 4000000: baudrate = B4000000; break;
  #endif
      default:
        baudrate = 0;
      }
    return baudrate;
  }
  #endif
  
  #ifdef DEBUG
  static void dump(const char *msg, unsigned char *packet, int len)
  {
    int i;
  
    printf("%s", msg);
    for (i = 0; i < len; i++)
      printf(" %02x", packet[i]);
    putchar('\n');
  }
  #endif
  
  static void message(serial_source src, serial_source_msg msg)
  {
    if (src->message)
      src->message(msg);
  }
  
  static int serial_read(serial_source src, int non_blocking, void *buffer, int n)
  {
  #ifndef LOSE32
    fd_set fds;
    int cnt;
  
    if (non_blocking)
      {
        cnt = read(src->fd, buffer, n);
  
        /* Work around buggy usb serial driver (returns 0 when no data
  	 is available). Mac OS X seems to like to do this too (at
  	 least with a Keyspan 49WG).
        */
        if (cnt == 0)
  	{
  	  cnt = -1;
  	  errno = EAGAIN;
  	}
        return cnt;
      }
    else
      for (;;)
        {
  	FD_ZERO(&fds);
  	FD_SET(src->fd, &fds);
  	cnt = select(src->fd + 1, &fds, NULL, NULL, NULL);
  	if (cnt < 0)
  	  return -1;
  
  	cnt = read(src->fd, buffer, n);
  	if (cnt != 0)
  	  return cnt;
        }
  #else // LOSE32
    int cnt;
  
    if (non_blocking) {
      ReadFile(src->hComm, buffer, n, &cnt, NULL);
  
      return cnt;
  
    } else {
        for (;;) {
            DWORD eventMask;
            SetCommMask(src->hComm, EV_RXCHAR);
            if (!WaitCommEvent(src->hComm, &eventMask, NULL)) {
                return -1;
            }
  
            ReadFile(src->hComm, buffer, n, &cnt, NULL);
  
            if (cnt != 0) {
              return cnt;
            }
        }
    }
  #endif
  }
  
  serial_source open_serial_source(const char *device, int baud_rate,
  				 int non_blocking,
  				 void (*message)(serial_source_msg problem))
  /* Effects: opens serial port device at specified baud_rate. If non_blocking
       is true, read_serial_packet calls will be non-blocking (writes are
       always blocking, for now at least)
     Returns: descriptor for serial forwarder at host:port, or
       NULL for failure (bad device or bad baud rate)
   */
  {
  #ifndef LOSE32
    struct termios newtio;
    int fd;
    tcflag_t baudflag = parse_baudrate(baud_rate);
  
    if (!baudflag)
      return NULL;
  
    fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0)
      return NULL;
  
  #ifdef __CYGWIN__
    /* For some very mysterious reason, this incantation is necessary to make
       the serial port work under some windows machines */
    HANDLE handle = (HANDLE)get_osfhandle(fd);
    DCB dcb;
    if (!(GetCommState(handle, &dcb) && SetCommState(handle, &dcb)))
      {
        close(fd);
        return NULL;
      }
  #endif
    /* Serial port setting */
    memset(&newtio, 0, sizeof(newtio));
    newtio.c_cflag = CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR | IGNBRK;
    cfsetispeed(&newtio, baudflag);
    cfsetospeed(&newtio, baudflag);
  
    /* Raw output_file */
    newtio.c_oflag = 0;
  
    if (tcflush(fd, TCIFLUSH) >= 0 &&
        tcsetattr(fd, TCSANOW, &newtio) >= 0)
      {
        serial_source src = malloc(sizeof *src);
  
        if (src)
  	{
  	  memset(src, 0, sizeof *src);
  	  src->fd = fd;
  	  src->non_blocking = non_blocking;
  	  src->message = message;
  	  src->send.seqno = 37;
  
  	  return src;
  	}
      }
    close(fd);
  
    return NULL;
  #else // LOSE32
  	LPCTSTR       ComName = (LPCTSTR)device;
      HANDLE        hComm;
  	DCB           dcb;
      serial_source src;
  
  	int buflen = MultiByteToWideChar(CP_ACP,0,(PCSTR)device,-1,(LPWSTR)ComName,0);
  	MultiByteToWideChar(CP_ACP,0,(PCSTR)device,-1,(LPWSTR)ComName,buflen);
  
  	//syncronize
  	hComm = CreateFile(ComName,  GENERIC_READ | GENERIC_WRITE,  0,  NULL,  OPEN_EXISTING,
  					FILE_ATTRIBUTE_NORMAL, NULL);
  
      if (hComm == INVALID_HANDLE_VALUE) {
          return NULL;
      }
  
      PurgeComm(hComm, PURGE_RXCLEAR);
  
  	GetCommState(hComm, &dcb);
  	dcb.BaudRate = baud_rate;
  	dcb.ByteSize = 8;
  	dcb.Parity = NOPARITY;
  	dcb.fParity = FALSE;
  	dcb.StopBits = ONESTOPBIT;
      if (SetCommState(hComm, &dcb) == 0) {
          return NULL;
      }
  
      src = malloc(sizeof *src);
  
      if (src) {
  	  memset(src, 0, sizeof *src);
  	  src->hComm = hComm;
  	  src->non_blocking = non_blocking;
  	  src->message = message;
  	  src->send.seqno = 37;
  
  	}
  
  	return src;
  
  #endif // LOSE32
  }
  
  #ifndef LOSE32
  int serial_source_fd(serial_source src)
  /* Returns: the file descriptor used by serial source src (useful when
       non-blocking reads were requested)
  */
  {
    return src->fd;
  }
  #endif
  
  #ifdef LOSE32
  HANDLE serial_source_handle(serial_source src)
  /* Returns: the file descriptor used by serial source src (useful when
       non-blocking reads were requested)
  */
  {
    return src->hComm;
  }
  #endif
  
  int close_serial_source(serial_source src)
  /* Effects: closes serial source src
     Returns: 0 if successful, -1 if some problem occured (but source is
       considered closed anyway)
   */
  {
  #ifndef LOSE32
    int ok = close(src->fd);
  #else
    int ok = CloseHandle(src->hComm);
  #endif
  
    free(src);
  
    return ok;
  }
  
  static int source_wait(serial_source src, struct timeval *deadline)
  /* Effects: waits until deadline for some data on source. deadline
       can be NULL for indefinite waiting.
     Returns: 0 if data is available, -1 if the deadline expires
  */
  {
  #ifndef LOSE32
    struct timeval tv;
    fd_set fds;
    int cnt;
  
    if (src->recv.bufpos < src->recv.bufused)
      return 0;
  
    for (;;)
      {
        if (deadline)
  	{
  	  gettimeofday(&tv, NULL);
  	  tv.tv_sec = deadline->tv_sec - tv.tv_sec;
  	  tv.tv_usec = deadline->tv_usec - tv.tv_usec;
  	  if (tv.tv_usec < 0)
  	    {
  	      tv.tv_usec += 1000000;
  	      tv.tv_sec--;
  	    }
  	  if (tv.tv_sec < 0)
  	    return -1;
  	}
  
        FD_ZERO(&fds);
        FD_SET(src->fd, &fds);
        cnt = select(src->fd + 1, &fds, NULL, NULL, deadline ? &tv : NULL);
        if (cnt < 0)
  	{
  	  if (errno == EINTR)
  	    continue;
  	  message(src, msg_unix_error);
  	  return -1;
  	}
        if (cnt == 0)
  	return -1;
        return 0;
      }
  #else // LOSE32
      // FIXME: the deadline is ignored here
  
      DWORD eventMask;
      SetCommMask(src->hComm, EV_RXCHAR);
      if (!WaitCommEvent(src->hComm, &eventMask, NULL)) {
          return -1;
      }
  
      return 0;
  
  #endif
  }
  
  static int source_write(serial_source src, const void *buffer, int count)
  {
  #ifndef LOSE32
    int actual = 0;
  
    if (fcntl(src->fd, F_SETFL, 0) < 0)
      {
        message(src, msg_unix_error);
        return -1;
      }
    while (count > 0)
      {
        int n = write(src->fd, buffer, count);
  
        if (n < 0 && errno == EINTR)
  	continue;
        if (n < 0)
  	{
  	  message(src, msg_unix_error);
  	  actual = -1;
  	  break;
  	}
  
        count -= n;
        actual += n;
        buffer += n;
      }
    if (fcntl(src->fd, F_SETFL, O_NONBLOCK) < 0)
      {
        message(src, msg_unix_error);
        /* We're in trouble, but there's no obvious fix. */
      }
    return actual;
  #else // LOSE32
      int actual = 0;
      int n;
      const unsigned char * b = buffer;
  
      while (count > 0) {
        if (!WriteFile(src->hComm, b, count, &n, NULL)) {
  	      message(src, msg_unix_error);
            actual = -1;
            break;
        }
  
        count  -= n;
        actual += n;
        b      += n;
      }
  
      return actual;
  #endif
  }
  
  static void push_protocol_packet(serial_source src,
  				 uint8_t type, uint8_t *packet, uint8_t len)
  {
    /* I'm assuming short queues */
    struct packet_list *entry = malloc(sizeof *entry), **last;
  
    if (!entry)
      {
        message(src, msg_no_memory);
        free(packet);
        return;
      }
  
    entry->packet = packet;
    entry->len = len;
    entry->next = NULL;
  
    last = &src->recv.queue[type];
    while (*last)
      last = &(*last)->next;
    *last = entry;
  }
  
  static struct packet_list *pop_protocol_packet(serial_source src, uint8_t type)
  {
    struct packet_list *entry = src->recv.queue[type];
  
    if (entry)
      src->recv.queue[type] = entry->next;
  
    return entry;
  }
  
  static bool packet_available(serial_source src, uint8_t type)
  {
    return src->recv.queue[type] != NULL;
  }
  
  int serial_source_empty(serial_source src)
  /* Returns: true if serial source does not contain any pending data, i.e.,
       if the result is true and there is no data available on the source's
       file descriptor, then read_serial_packet will:
         - return NULL if the source is non-blocking
         - block if it is blocking
  
      (Note: the presence of this calls allows the serial_source to do some
      internal buffering)
  */
  {
    return src->recv.bufpos >= src->recv.bufused &&
      !packet_available(src, P_PACKET_NO_ACK);
  }
  
  /* Slow implementation of crc function */
  static uint16_t crc_byte(uint16_t crc, uint8_t b)
  {
    uint8_t i;
  
    crc = crc ^ b << 8;
    i = 8;
    do
      if (crc & 0x8000)
        crc = crc << 1 ^ 0x1021;
      else
        crc = crc << 1;
    while (--i);
  
    return crc;
  }
  
  static uint16_t crc_packet(uint8_t *data, int len)
  {
    uint16_t crc = 0;
  
    while (len-- > 0)
      crc = crc_byte(crc, *data++);
  
    return crc;
  }
  
  static int read_byte(serial_source src, int non_blocking)
  /* Returns: next byte (>= 0), or -1 if no data available and non-blocking is true.
  */
  {
    if (src->recv.bufpos >= src->recv.bufused)
      {
        for (;;)
  	{
  	  int n = serial_read(src, non_blocking, src->recv.buffer, sizeof src->recv.buffer);
  
  	  if (n == 0) /* Can't occur because of serial_read bug workaround */
  	    {
  	      message(src, msg_closed);
  	      return -1;
  	    }
  	  if (n > 0)
  	    {
  #ifdef DEBUG
  	      dump("raw", src->recv.buffer, n);
  #endif
  	      src->recv.bufpos = 0;
  	      src->recv.bufused = n;
  	      break;
  	    }
  #ifndef LOSE32
  	  if (errno == EAGAIN)
  	    return -1;
  	  if (errno != EINTR)
  	    message(src, msg_unix_error);
  #endif
      }
      }
    //printf("in %02x\n", src->recv.buffer[src->recv.bufpos]);
    return src->recv.buffer[src->recv.bufpos++];
  }
  
  static void process_packet(serial_source src, uint8_t *packet, int len);
  static int write_framed_packet(serial_source src,
  			       uint8_t packet_type, uint8_t first_byte,
  			       const uint8_t *packet, int count);
  
  static void read_and_process(serial_source src, int non_blocking)
  /* Effects: reads and processes up to one packet.
  */
  {
    uint8_t *packet = src->recv.packet;
  
    for (;;)
      {
        int byte = read_byte(src, non_blocking);
  
        if (byte < 0)
  	return;
  
        if (!src->recv.in_sync)
  	{
  	  if (byte == SYNC_BYTE)
  	    {
  	      src->recv.in_sync = TRUE;
  	      message(src, msg_sync);
  	      src->recv.count = 0;
  	      src->recv.escaped = FALSE;
  	    }
  	  continue;
  	}
        if (src->recv.count >= MTU)
  	{
  	  message(src, msg_too_long);
  	  src->recv.in_sync = FALSE;
  	  continue;
  	}
        if (src->recv.escaped)
  	{
  	  if (byte == SYNC_BYTE)
  	    {
  	      /* sync byte following escape is an error, resync */
  	      message(src, msg_bad_sync);
  	      src->recv.in_sync = FALSE;
  	      continue;
  	    }
  	  byte ^= 0x20;
  	  src->recv.escaped = FALSE;
  	}
        else if (byte == ESCAPE_BYTE)
  	{
  	  src->recv.escaped = TRUE;
  	  continue;
  	}
        else if (byte == SYNC_BYTE)
  	{
  	  int count = src->recv.count;
  	  uint8_t *received;
  	  uint16_t read_crc, computed_crc;
  
  	  src->recv.count = 0; /* ready for next packet */
  
  	  if (count < 4)
  	    /* frames that are too small are ignored */
  	    continue;
  
  	  received = malloc(count - 2);
  	  if (!received)
  	    {
  	      message(src, msg_no_memory);
  	      continue;
  	    }
  	  memcpy(received, packet, count - 2);
  
  	  read_crc = packet[count - 2] | packet[count - 1] << 8;
  	  computed_crc = crc_packet(received, count - 2);
  
  #ifdef DEBUG
  	  dump("received", packet, count);
  	  printf("  crc %x comp %x\n", read_crc, computed_crc);
  #endif
  	  if (read_crc == computed_crc)
  	    {
  	      process_packet(src, received, count - 2);
  	      return; /* give rest of world chance to do something */
  	    }
  	  else
  	    {
  	      message(src, msg_bad_crc);
  	      free(received);
  	      /* We don't lose sync here. If we did, garbage on the line
  		 at startup will cause loss of the first packet. */
  	      continue;
  	    }
  	}
        packet[src->recv.count++] = byte;
      }
  }
  
  static void process_packet(serial_source src, uint8_t *packet, int len)
  {
    int packet_type = packet[0], offset = 1;
  
    if (packet_type == P_PACKET_ACK)
      {
        /* send ack */
        write_framed_packet(src, P_ACK, packet[1], NULL, 0);
        /* And merge with un-acked packets */
        packet_type = P_PACKET_NO_ACK;
        offset = 2;
      }
    /* packet must remain a valid pointer to pass to free. So we move the
       data rather than pass an internal pointer */
    memmove(packet, packet + offset, len - offset);
    push_protocol_packet(src, packet_type, packet, len - offset);
  }
  
  void *read_serial_packet(serial_source src, int *len)
  /* Effects: Read the serial source src. If a packet is available, return it.
       If in blocking mode and no packet is available, wait for one.
     Returns: the packet read (in newly allocated memory), with *len is
       set to the packet length, or NULL if no packet is yet available and
       the serial source is in non-blocking mode
  */
  {
    read_and_process(src, TRUE);
    for (;;)
      {
        struct packet_list *entry;
  
        entry = pop_protocol_packet(src, P_PACKET_NO_ACK);
        if (entry)
  	{
  	  uint8_t *packet = entry->packet;
  
  	  *len = entry->len;
  	  free(entry);
  
  	  return packet;
  	}
        if (src->non_blocking && serial_source_empty(src))
  	return NULL;
        source_wait(src, NULL);
        read_and_process(src, src->non_blocking);
      }
  }
  
  /* The escaper does the sync bytes+escape-like encoding+crc of packets */
  
  static void escape_add(serial_source src, uint8_t b)
  {
    src->send.escaped[src->send.escapeptr++] = b;
  }
  
  static int init_escaper(serial_source src, int count)
  {
    src->send.escaped = malloc(count * 2 + 2);
    if (!src->send.escaped)
      {
        message(src, msg_no_memory);
        return -1;
      }
    src->send.escapeptr = 0;
    src->send.crc = 0;
  
    escape_add(src, SYNC_BYTE);
  
    return 0;
  }
  
  static void terminate_escaper(serial_source src)
  {
    escape_add(src, SYNC_BYTE);
  }
  
  static void escape_byte(serial_source src, uint8_t b)
  {
    src->send.crc = crc_byte(src->send.crc, b);
    if (b == SYNC_BYTE || b == ESCAPE_BYTE)
      {
        escape_add(src, ESCAPE_BYTE);
        escape_add(src, b ^ 0x20);
      }
    else
      escape_add(src, b);
  }
  
  static void free_escaper(serial_source src)
  {
    free(src->send.escaped);
  }
  
  // Write a packet of type 'packetType', first byte 'firstByte'
  // and bytes 2..'count'+1 in 'packet'
  static int write_framed_packet(serial_source src,
  			       uint8_t packet_type, uint8_t first_byte,
  			       const uint8_t *packet, int count)
  {
    int i, crc;
  
  #ifdef DEBUG
    printf("writing %02x %02x", packet_type, first_byte);
    dump("", packet, count);
  #endif
  
    if (init_escaper(src, count + 4) < 0)
      return -1;
  
    escape_byte(src, packet_type);
    escape_byte(src, first_byte);
    for (i = 0; i < count; i++)
      escape_byte(src, packet[i]);
  
    crc = src->send.crc;
    escape_byte(src, crc & 0xff);
    escape_byte(src, crc >> 8);
  
    terminate_escaper(src);
  
  #ifdef DEBUG
    dump("encoded", src->send.escaped, src->send.escapeptr);
  #endif
  
    if (source_write(src, src->send.escaped, src->send.escapeptr) < 0)
      {
        free_escaper(src);
        return -1;
      }
    free_escaper(src);
    return 0;
  }
  
  static void add_timeval(struct timeval *tv, long us)
  /* Specialised for this app */
  {
    tv->tv_sec += us / 1000000;
    tv->tv_usec += us % 1000000;
    if (tv->tv_usec > 1000000)
      {
        tv->tv_usec -= 1000000;
        tv->tv_sec++;
      }
  }
  
  int write_serial_packet(serial_source src, const void *packet, int len)
  /* Effects: writes len byte packet to serial source src
     Returns: 0 if packet successfully written, 1 if successfully written
       but not acknowledged, -1 otherwise
  */
  {
    struct timeval deadline;
  
    src->send.seqno++;
    if (write_framed_packet(src, P_PACKET_ACK, src->send.seqno, packet, len) < 0)
      return -1;
  
    // FIXME: the WIN32 implementation of source_wait()
    //        disregards the deadline parameter anyway
  #ifndef LOSE32
    gettimeofday(&deadline, NULL);
    add_timeval(&deadline, ACK_TIMEOUT);
  #endif
  
    for (;;)
      {
        struct packet_list *entry;
  
        read_and_process(src, TRUE);
        entry = pop_protocol_packet(src, P_ACK);
        if (entry)
  	{
  	  uint8_t acked = entry->packet[0];
  
  	  free(entry->packet);
  	  free(entry);
  	  if (acked == src->send.seqno)
  	    return 0;
  	}
        else if (source_wait(src, &deadline) < 0)
  	return 1;
      }
  }
  
  /* This somewhat convoluted code allows us to use a common baudrate table
     with the Java code. This could be improved if we generated the Java
     code from a common table.
  */
  
  struct pargs {
    char *name;
    int rate;
  };
  
  static void padd(struct pargs *args, const char *name, int baudrate)
  {
    if (!strcmp(args->name, name))
      args->rate = baudrate;
  }
  
  static void init(void) { }
  
  int platform_baud_rate(char *platform_name)
  /* Returns: The baud rate of the specified platform, or -1 for unknown
       platforms
  */
  {
    /* The Java code looks like Platform.add(Platform.x, "name", baudrate);
       Fake up some C stuff which will make that work right. */
    struct pargs args;
    struct {
      void (*add)(struct pargs *args, const char *name, int baudrate);
      struct pargs *x;
    } Platform = { padd, &args };
    static struct {
      struct {
        int packet;
      } tinyos;
    } net;
  
    if (isdigit(platform_name[0]))
      return atoi(platform_name);
  
    args.name = platform_name;
    args.rate = -1;
  
  #define class
  #define BaudRate
  #define static
  #define void
  #define throws ;
  #define Exception
  #define package
  #include "../../java/net/tinyos/packet/BaudRate.java"
  
    return args.rate;
  }
  