"Fossies" - the Fresh Open Source Software Archive

Member "heaplayers-351/benchmarks/mudlle/ports.c" (15 Oct 2003, 15770 Bytes) of package /linux/misc/old/heaplayers_3_5_1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ports.c" see the Fossies "Dox" file reference documentation.

    1 /* $Log: ports.c,v $
    2 /* Revision 1.1  2003/10/15 15:58:59  emery
    3 /* Initial check-in.
    4 /*
    5 /* Revision 1.1  2001/08/23 17:20:15  emery
    6 /* The big fig newton.
    7 /*
    8 /* Revision 1.1.1.1  2001/06/28 19:48:18  dgay
    9 /* Initial import of RC tests
   10 /*
   11  * Revision 1.29  1997/08/04 22:17:15  arda
   12  * Fix mudlle so that it compiles with g++
   13  *
   14  * Revision 1.28  1996/04/22 23:08:32  arda
   15  * Backup.
   16  *
   17  * Revision 1.27  1996/02/09 14:58:47  arda
   18  * Security holes
   19  *
   20  * Revision 1.26  1995/09/02  18:25:43  arda
   21  * ?
   22  *
   23  * Revision 1.25  1995/04/29  20:05:22  arda
   24  * fix
   25  *
   26  * Revision 1.24  1995/03/06  20:28:46  arda
   27  * make server
   28  *
   29  * Revision 1.23  1995/02/12  18:20:04  arda
   30  * (CLI) Unknown...
   31  *
   32  * Revision 1.22  1995/01/21  17:47:46  arda
   33  * Cli mods
   34  *
   35  * Revision 1.21  1995/01/09  17:33:58  arda
   36  * First masun1 commit?
   37  *
   38  * Revision 1.20  1994/10/09  06:42:52  arda
   39  * Libraries
   40  * Type inference
   41  * Many minor improvements
   42  *
   43  * Revision 1.19  1994/08/26  08:51:43  arda
   44  * Keep free block list for string ports.
   45  *
   46  * Revision 1.18  1994/08/22  11:18:39  arda
   47  * Moved code allocation to ins.c
   48  * Changes for mudlle compiler in MUME.
   49  *
   50  * Revision 1.17  1994/08/16  19:16:13  arda
   51  * Mudlle compiler for sparc now fully functional (68k compiler now needs
   52  * updating for primitives).
   53  * Changes to allow Sparc trap's for runtime errors.
   54  * Also added flags to primitives for better calling sequences.
   55  *
   56  * Revision 1.14  1994/02/11  09:59:18  dgay
   57  * Owl: -Wall
   58  *      new shared string handling
   59  *      configuration file
   60  *
   61  * Revision 1.13  1994/01/02  15:50:14  arda
   62  * bug fix
   63  *
   64  * Revision 1.12  1993/11/27  17:24:11  arda
   65  * Owl: The promised bug fixes.
   66  *
   67  * Revision 1.11  1993/11/27  11:29:05  arda
   68  * Owl: Major changes to affect.
   69  *      Save mudlle data with players & objects.
   70  *      Change skill format on disk.
   71  *      Other minor changes.
   72  *      Still needs full debugging.
   73  *
   74  * Revision 1.10  1993/08/28  17:01:27  un_autre
   75  * SIZE OF ARMORS (CLI)
   76  *
   77  * Revision 1.9  1993/08/14  16:43:15  un_mec
   78  * Owl: Improved vpprintf
   79  *      New input system (with an input stack) => small changes to interact
   80  *      New identifier rules (lexer.l)
   81  *
   82  * Revision 1.8  1993/07/21  20:36:58  un_mec
   83  * Owl: Added &&, ||, optimised if.
   84  *      Added branches to the intermediate language.
   85  *      Separated destiniation language generation into ins module
   86  *      (with some peephole optimisation)
   87  *      Standalone version of mudlle (mkf, runtime/mkf, mudlle.c) added to CVS
   88  *
   89  * Revision 1.7  1993/06/28  21:04:07  un_mec
   90  * Last protocol bugs fixed :-) ?
   91  *
   92  * Revision 1.6  1993/06/28  19:12:08  un_autre
   93  * Bug fix of previous changes:
   94  *   - /num <x> <regexp>
   95  *   - improved cprintf (field width)
   96  *   - edit("person/file")
   97  *
   98  * Revision 1.5  1993/06/25  15:37:57  un_autre
   99  * *** empty log message ***
  100  *
  101  * Revision 1.4  1993/06/20  13:35:21  un_mec
  102  * Owl: edit protocol bug fix.
  103  *
  104  * Revision 1.3  1993/05/29  11:42:10  un_mec
  105  * Owl: MUME protocol added.
  106  *
  107  * Revision 1.2  1993/05/07  23:23:59  un_autre
  108  * *** empty log message ***
  109  *
  110  * Revision 1.1  1993/05/02  07:37:57  un_mec
  111  * Owl: New output (mudlle ports).
  112  *
  113  * Revision 1.2  1992/04/11  14:44:11  gay_d
  114  * Nothing important
  115  *
  116  * Revision 1.1  1992/02/20  17:48:08  gay_d
  117  * Initial revision
  118  * */
  119 
  120 static char rcsid[] = "$Id: ports.c,v 1.1 2003/10/15 15:58:59 emery Exp $";
  121 
  122 #include <assert.h>
  123 #include <stdarg.h>
  124 #include <errno.h>
  125 #include <string.h>
  126 #include <ctype.h>
  127 #include "mudlle.h"
  128 #include "types.h"
  129 #include "alloc.h"
  130 #include "ports.h"
  131 #include "utils.h"
  132 
  133 #ifdef MUME
  134 #include "handler.sock.h"
  135 #include "../server/comm.h"
  136 #endif
  137 
  138 /* The various types of input & output ports */
  139 
  140 
  141 #define STRING_BLOCK_SIZE 512   /* Size of each block */
  142 
  143 struct string_oport_block /* A structure in which to accumulate output */
  144 {
  145   struct obj o;
  146   struct string_oport_block *next;
  147   struct string *data;
  148 };
  149 /* sizeof(struct string_oport_block) should equal BLOCK_SIZE (see calloc.c)
  150    exactly, otherwise some memory will be wasted. */
  151 
  152 struct string_oport /* Output to a string */
  153 {
  154   struct oport p;
  155   struct string_oport_block *first, *current;
  156   value pos;
  157 };
  158 
  159 struct file_oport /* Output to a FILE * */
  160 {
  161   struct oport p;
  162   struct gtemp *file;
  163 };
  164 
  165 
  166 static struct string_oport_block *free_blocks;
  167 
  168 /* Creation & code for the various types of ports */
  169 /* ---------------------------------------------- */
  170 
  171 static void init_outputport(struct oport *p, struct oport_methods *m)
  172 {
  173 }
  174 
  175 static struct string_oport_block *new_string_block(void)
  176 {
  177   struct string_oport_block *newp;
  178 
  179   if (free_blocks) 
  180     {
  181       newp = free_blocks;
  182       free_blocks = free_blocks->next;
  183     }
  184   else
  185     {
  186       struct gcpro gcpro1;
  187       struct string *s;
  188 
  189       s = (struct string *)allocate_string(type_internal, STRING_BLOCK_SIZE);
  190       GCPRO1(s);
  191       newp = (struct string_oport_block *)allocate_record(type_internal, 2);
  192       UNGCPRO();
  193       newp->data = s;
  194     }
  195 
  196   newp->next = NULL;
  197   
  198   return newp;
  199 }
  200 
  201 static void output_string_close(struct oport *_p)
  202 {
  203   struct string_oport *p = (struct string_oport *)_p;
  204   
  205   p->p.methods = NULL;
  206 
  207   /* Free data (add blocks to free block list) */
  208   p->current->next = free_blocks;
  209   free_blocks = p->first;
  210   p->first = p->current = NULL;
  211 }
  212 
  213 static void string_flush(struct oport *_p)
  214 {
  215 }
  216      
  217 static void string_putc(struct oport *_p, char c)
  218 {
  219   struct string_oport *p = (struct string_oport *)_p;
  220   struct string_oport_block *current = p->current;
  221   long pos = intval(p->pos);
  222   
  223   if (pos == STRING_BLOCK_SIZE)
  224     {
  225       struct string_oport_block *blk;
  226       struct gcpro gcpro1;
  227 
  228       GCPRO1(p);
  229       blk = new_string_block();
  230       UNGCPRO();
  231       p->current = current->next = blk;
  232       current = p->current;
  233       p->pos = makeint(pos = 0);
  234     }
  235   current->data->str[pos++] = c;
  236   p->pos = makeint(pos);
  237 }
  238 
  239 static void string_write(struct oport *_p, const char *data, int nchars)
  240 {
  241   struct string_oport *p = (struct string_oport *)_p;
  242   struct string_oport_block *current = p->current;
  243   int fit;
  244   long pos = intval(p->pos);
  245   struct gcpro gcpro1, gcpro2;
  246 
  247   GCPRO2(p, current);
  248   while ((fit = STRING_BLOCK_SIZE - pos) < nchars)
  249     {
  250       struct string_oport_block *blk = new_string_block();
  251 
  252       memcpy(current->data->str + pos, data, fit);
  253       p->current = current->next = blk;
  254       current = p->current;
  255       data += fit;
  256       nchars -= fit;
  257       pos = 0;
  258     }
  259   UNGCPRO();
  260   memcpy(current->data->str + pos, data, nchars);
  261   p->pos = makeint(pos + nchars);
  262 }
  263 
  264 static void string_swrite(struct oport *_p, struct string *s, int from, int nchars)
  265 {
  266   struct string_oport *p = (struct string_oport *)_p;
  267   struct string_oport_block *current = p->current;
  268   int fit;
  269   long pos = intval(p->pos);
  270   struct gcpro gcpro1, gcpro2, gcpro3;
  271 
  272   GCPRO2(p, current);
  273   GCPRO(gcpro3, s);
  274   while ((fit = STRING_BLOCK_SIZE - pos) < nchars)
  275     {
  276       struct string_oport_block *blk = new_string_block();
  277 
  278       memcpy(current->data->str + pos, s->str + from, fit);
  279       p->current = current->next = blk;
  280       current = p->current;
  281       from += fit;
  282       nchars -= fit;
  283       pos = 0;
  284     }
  285   UNGCPRO();
  286   memcpy(current->data->str + pos, s->str + from, nchars);
  287   p->pos = makeint(pos + nchars);
  288 }
  289 
  290 static struct oport_methods string_port_methods = {
  291   output_string_close,
  292   string_putc,
  293   string_write,
  294   string_swrite,
  295   string_flush
  296 };
  297 
  298 value make_string_outputport()
  299 {
  300   struct string_oport *p = (struct string_oport *) allocate_record(type_outputport, 4);
  301   struct gcpro gcpro1;
  302   struct gtemp *m;
  303   struct string_oport_block *blk;
  304 
  305   GCPRO1(p);
  306   m = allocate_temp(type_internal, &string_port_methods);
  307   p->p.methods = m;
  308   blk = new_string_block();
  309   p->first = p->current = blk;
  310   p->pos = makeint(0);
  311   UNGCPRO();
  312 
  313   return p;
  314 }
  315 
  316 static void output_file_close(struct oport *_p)
  317 {
  318   struct file_oport *p = (struct file_oport *)_p;
  319   FILE *f = p->file->external;
  320 
  321   fclose(f);
  322   p->file->external = NULL;
  323 }
  324 
  325 static void file_flush(struct oport *_p)
  326 {
  327   struct file_oport *p = (struct file_oport *)_p;
  328   FILE *f = p->file->external;
  329 
  330   fflush(f);
  331 }
  332      
  333 static void file_putc(struct oport *_p, char c)
  334 {
  335   struct file_oport *p = (struct file_oport *)_p;
  336   FILE *f = p->file->external;
  337 
  338   if (f) putc(c, f);
  339 }
  340 
  341 static void file_write(struct oport *_p, const char *data, int nchars)
  342 {
  343   struct file_oport *p = (struct file_oport *)_p;
  344   FILE *f = p->file->external;
  345 
  346   if (f) fwrite(data, nchars, 1, f);
  347 }
  348 
  349 static void file_swrite(struct oport *_p, struct string *s, int from, int nchars)
  350 {
  351   struct file_oport *p = (struct file_oport *)_p;
  352   FILE *f = p->file->external;
  353 
  354   if (f) fwrite(s->str + from, nchars, 1, f);
  355 }
  356 
  357 static struct oport_methods file_port_methods = {
  358   output_file_close,
  359   file_putc,
  360   file_write,
  361   file_swrite,
  362   file_flush
  363 };
  364 
  365 value make_file_outputport(FILE *f)
  366 {
  367   struct file_oport *p = (struct file_oport *) allocate_record(type_outputport, 2);
  368   struct gcpro gcpro1;
  369   struct gtemp *m;
  370 
  371   GCPRO1(p);
  372   m = allocate_temp(type_internal, &file_port_methods);
  373   p->p.methods = m;
  374   m = allocate_temp(type_internal, f);
  375   p->file = m;
  376   UNGCPRO();
  377 
  378   return p;
  379 }
  380 
  381 int port_empty(struct oport *_p)
  382 /* Return: true if the port is empty
  383    Requires: p be a string-type output port
  384 */
  385 {
  386   struct string_oport *p = (struct string_oport *)_p;
  387   struct string_oport_block *current = p->first;
  388 
  389   return !current->next && intval(p->pos) == 0;
  390 }
  391 
  392 static ulong port_length(struct string_oport *p)
  393 {
  394   struct string_oport_block *current = p->first;
  395   ulong size;
  396 
  397   size = 0;
  398   while (current->next)
  399     {
  400       size += STRING_BLOCK_SIZE;
  401       current = current->next;
  402     }
  403   return size + intval(p->pos);
  404 }
  405 
  406 static void port_copy(char *s, struct string_oport *p)
  407 {
  408   struct string_oport_block *current = p->first;
  409   long pos = intval(p->pos);
  410 
  411   while (current->next)
  412     {
  413       memcpy(s, current->data->str, STRING_BLOCK_SIZE);
  414       s += STRING_BLOCK_SIZE;
  415       current = current->next;
  416     }
  417   memcpy(s, current->data->str, pos);
  418   s[pos] = '\0';
  419 }
  420 
  421 struct string *port_string(struct oport *_p)
  422 {
  423   struct string_oport *p = (struct string_oport *)_p;
  424   struct gcpro gcpro1;
  425   struct string *result;
  426 
  427   GCPRO1(p);
  428   result = (struct string *)allocate_string(type_string, port_length(p) + 1);
  429   UNGCPRO();
  430 
  431   port_copy(result->str, p);
  432 
  433   return result;
  434 }
  435 
  436 char *port_cstring(struct oport *_p)
  437 {
  438   struct string_oport *p = (struct string_oport *)_p;
  439   char *s;
  440 
  441   s = xmalloc(port_length(p) + 1);
  442   port_copy(s, p);
  443 
  444   return s;
  445 }
  446 
  447 void port_append(struct oport *p1, struct oport *_p2)
  448 /* Effects: The characters of port p2 are appended to the end of port p1.
  449    Modifies: p1
  450    Requires: p2 be a string-type output port
  451 */
  452 {
  453   struct string_oport *p2 = (struct string_oport *)_p2;
  454   struct string_oport_block *current = p2->first;
  455   long pos = intval(p2->pos);
  456   struct gcpro gcpro1, gcpro2;
  457 
  458   GCPRO2(p1, current);
  459   while (current->next)
  460     {
  461       pswrite(p1, current->data, 0, STRING_BLOCK_SIZE);
  462       current = current->next;
  463     }
  464   pswrite(p1, current->data, 0, pos);
  465   UNGCPRO();
  466 }
  467 
  468 #ifdef MUME
  469 int port_dump(struct descriptor_data *t)
  470 /* Effects: Sends all data sent to port p to descriptor fd, except for
  471      the first 'from' characters.
  472    Returns: 0 if all output sent,
  473      -1 in case of an error (errno contains more information)
  474      the # of characters sent otherwise.
  475    Requires: p be a string-type output port
  476 */
  477 {
  478   ulong sent = 0;
  479   int cnt, tosend;
  480 
  481   struct oport *_p = t->sending.obj;
  482   int fd = t->descriptor;
  483   ulong from = t->sendpos;
  484 
  485   struct string_oport *p = (struct string_oport *)_p;
  486   struct string_oport_block *current = p->first;
  487 
  488   while (current->next)
  489     {
  490       if (from >= STRING_BLOCK_SIZE)
  491     {
  492       from -= STRING_BLOCK_SIZE;
  493       current = current->next;
  494     }
  495       else
  496     {
  497       tosend = STRING_BLOCK_SIZE - from;
  498 
  499       cnt = server_mux_send(t,current->data->str + from, tosend);
  500 
  501       if (cnt < 0)
  502         if ((errno == EWOULDBLOCK || errno == EAGAIN) && sent)
  503           return sent;  /* 0 is for send complete */
  504         else
  505           return -1;
  506 
  507       sent += cnt;
  508       if (cnt != tosend) return sent;
  509       current = current->next;
  510       from = 0;
  511     }
  512     }
  513   tosend = intval(p->pos) - from;
  514   if (tosend <= 0) return 0;    /* All done */
  515 
  516   cnt = server_mux_send(t,current->data->str + from, tosend);
  517 
  518   if (cnt == tosend) return 0;  /* All done */
  519   if (cnt < 0)
  520     if ((errno == EWOULDBLOCK || errno == EAGAIN) && sent)
  521       return sent;      /* 0 is for send complete */
  522     else
  523       return -1;
  524 
  525   return sent + cnt;
  526 }
  527 #endif
  528 
  529 /* C I/O routines for use with the ports */
  530 /* ------------------------------------- */
  531 
  532 void pputs(const char *s, struct oport *p)
  533 {
  534   opwrite(p, s, strlen(s));
  535 }
  536 
  537 static char basechars[17] = "0123456789abcdef";
  538 
  539 char *int2str(char *str, int base, ulong n, int is_signed)
  540 /* Requires: base be 2, 8, 10 or 16. str be at least INTSTRLEN characters long.
  541    Effects: Prints the ASCII representation of n in base base to the
  542      string str.
  543      If is_signed is TRUE, n is actually a long
  544    Returns: A pointer to the start of the result.
  545 */
  546 {
  547   char *pos;
  548   int minus;
  549 
  550   /* ints are 32 bits, the longest number will thus be
  551      32 digits (in binary) + 1(sign) characters long */
  552   pos = str + INTSTRLEN - 1;
  553   *--pos = '\0';
  554 
  555   if (is_signed && (long)n < 0)
  556     {
  557       minus = TRUE;
  558       n = -(long)n;
  559     }
  560   else minus = FALSE;
  561 
  562   do {
  563     *--pos = basechars[n % base];
  564     n /= base;
  565   } while (n > 0);
  566   if (minus) *--pos = '-';
  567 
  568   return pos;
  569 }
  570 
  571 void vpprintf(struct oport *p, const char *fmt, va_list args)
  572 {
  573   const char *percent, *add = NULL;
  574   char buf[INTSTRLEN];
  575   int longfmt, padright, fsize, addlen, cap;
  576   struct gcpro gcpro1;
  577 
  578   if (!p || !p->methods) return;
  579   GCPRO1(p);
  580   while (percent = strchr(fmt, '%'))
  581     {
  582       opwrite(p, fmt, percent - fmt);
  583       fmt = percent + 1;
  584       longfmt = FALSE;
  585       fsize = 0;
  586       padright = FALSE;
  587       cap = FALSE;
  588       if (*fmt == '-')
  589     {
  590       padright = TRUE;
  591       fmt++;
  592     }
  593       while (isdigit(*fmt))
  594     {
  595       fsize = fsize * 10 + *fmt - '0';
  596       fmt++;
  597     }
  598       if (*fmt == 'l')
  599     {
  600       longfmt = TRUE;
  601       fmt++;
  602     }
  603       switch (*fmt)
  604     {
  605     case '%':
  606       add = "%";
  607       break;
  608     case 'd': case 'i':
  609       if (longfmt)
  610         add = int2str(buf, 10, va_arg(args, long), TRUE);
  611       else
  612         add = int2str(buf, 10, va_arg(args, int), TRUE);
  613       break;
  614     case 'u':
  615       if (longfmt)
  616         add = int2str(buf, 10, va_arg(args, unsigned long), FALSE);
  617       else
  618         add = int2str(buf, 10, va_arg(args, unsigned int), FALSE);
  619       break;
  620     case 'x':
  621       if (longfmt)
  622         add = int2str(buf, 16, va_arg(args, unsigned long), FALSE);
  623       else
  624         add = int2str(buf, 16, va_arg(args, unsigned int), FALSE);
  625       break;
  626     case 'o':
  627       if (longfmt)
  628         add = int2str(buf, 8, va_arg(args, unsigned long), FALSE);
  629       else
  630         add = int2str(buf, 8, va_arg(args, unsigned int), FALSE);
  631       break;
  632     case 'S':
  633       cap = TRUE;
  634     case 's':
  635       add = va_arg(args, const char *);
  636       if (!add) add = "(null)";
  637       break;
  638     case 'c':
  639       add = buf;
  640       buf[0] = va_arg(args, int); buf[1] = '\0';
  641       break;
  642     case 'f':
  643       sprintf(buf, "%f", va_arg(args, double));
  644       add = buf;
  645       break;
  646     default: assert(0);
  647     }
  648       fmt++;
  649 
  650       addlen = strlen(add);
  651       if (fsize > 0 && !padright)
  652     {
  653       int i = fsize - addlen;
  654 
  655       while (--i >= 0) pputc(' ', p);
  656     }
  657       if (cap && addlen > 0)
  658     {
  659       pputc(toupper(add[0]), p);
  660       opwrite(p, add + 1, addlen - 1);
  661     }
  662       else
  663     opwrite(p, add, addlen);
  664       if (fsize > 0 && padright)
  665     {
  666       int i = fsize - addlen;
  667 
  668       while (--i >= 0) pputc(' ', p);
  669     }
  670     }
  671   pputs(fmt, p);
  672   UNGCPRO();
  673 }
  674 
  675 void pprintf(struct oport *p, const char *fmt, ...)
  676 {
  677   va_list args;
  678   
  679   va_start(args, fmt);
  680   vpprintf(p, fmt, args);
  681   va_end(args);  
  682 }
  683 
  684 void ports_init(void)
  685 {
  686   staticpro((value *)&free_blocks);
  687 }