Lichen

templates/native.c

338:61776a5a0e16
2016-12-07 Paul Boddie Associate constant name information with references so that structure members such as function instance default members can be generated statically, thus eliminating unnecessary structure initialisation in the translated code. Improved the determination of dynamic functions in the importer to consider only non-constant defaults.
     1 #include <stdlib.h> /* abs, exit */     2 #include <unistd.h> /* read, write */     3 #include <limits.h> /* INT_MAX, INT_MIN */     4 #include <math.h>   /* ceil, log10, pow */     5 #include <string.h> /* strcmp, strncpy, strlen */     6 #include <stdio.h>  /* fdopen, snprintf */     7 #include <errno.h>  /* errno */     8 #include "types.h"     9 #include "exceptions.h"    10 #include "ops.h"    11 #include "progconsts.h"    12 #include "progops.h"    13 #include "progtypes.h"    14 #include "main.h"    15     16 /* Utility functions. */    17     18 static __attr __new_int(int i)    19 {    20     /* Create a new integer and mutate the __data__ attribute. */    21     __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int));    22     attr.value->attrs[__pos___data__].intvalue = i;    23     return attr;    24 }    25     26 static __attr __new_str(char *s)    27 {    28     /* Create a new string and mutate the __data__ attribute. */    29     __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));    30     attr.value->attrs[__pos___data__].strvalue = s;    31     return attr;    32 }    33     34 static __attr __new_list(__fragment *f)    35 {    36     /* Create a new list and mutate the __data__ attribute. */    37     __attr attr = __new(&__InstanceTable___builtins___list_list, &__builtins___list_list, sizeof(__obj___builtins___list_list));    38     attr.value->attrs[__pos___data__].seqvalue = f;    39     return attr;    40 }    41     42 static __fragment *__fragment_append(__fragment *data, __attr * const value)    43 {    44     __fragment *newdata = data;    45     unsigned int size = data->size, capacity = data->capacity;    46     unsigned int n;    47     48     /* Re-allocate the fragment if the capacity has been reached. */    49     if (size >= capacity)    50     {    51         /* NOTE: Consider various restrictions on capacity increases. */    52         n = capacity ? capacity * 2 : 1;    53         newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));    54         newdata->capacity = n;    55     }    56     57     /* Insert the new element and increment the list size. */    58     newdata->attrs[size] = *value;    59     newdata->size = size + 1;    60     61     return newdata;    62 }    63     64 /* Native functions. */    65     66 __attr __fn_native__exit(__attr __args[])    67 {    68     __attr * const status = &__args[1];    69     70     exit(__load_via_object(status->value, __pos___data__).intvalue);    71     return __builtins___none_None;    72 }    73     74 __attr __fn_native__get_argv(__attr __args[])    75 {    76     __attr * const status = &__args[1];    77     78     /* NOTE: To be written. */    79     return __builtins___none_None;    80 }    81     82 __attr __fn_native__get_path(__attr __args[])    83 {    84     __attr * const status = &__args[1];    85     86     /* NOTE: To be written. */    87     return __builtins___none_None;    88 }    89     90 __attr __fn_native__is(__attr __args[])    91 {    92     __attr * const x = &__args[1];    93     __attr * const y = &__args[2];    94     95     return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False;    96 }    97     98 __attr __fn_native__is_not(__attr __args[])    99 {   100     __attr * const x = &__args[1];   101     __attr * const y = &__args[2];   102    103     return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False;   104 }   105    106 __attr __fn_native__get_maxint(__attr __args[])   107 {   108     __attr * const status = &__args[1];   109    110     return __new_int(INT_MAX);   111 }   112    113 __attr __fn_native__get_minint(__attr __args[])   114 {   115     __attr * const status = &__args[1];   116    117     return __new_int(INT_MIN);   118 }   119    120 __attr __fn_native__int_add(__attr __args[])   121 {   122     __attr * const _data = &__args[1];   123     __attr * const other = &__args[2];   124     /* _data and other interpreted as int */   125     int i = _data->intvalue;   126     int j = other->intvalue;   127    128     /* Test for overflow. */   129     if (((i > 0) && (j > 0) && (i > INT_MAX - j)) ||   130         ((i < 0) && (j < 0) && (i < INT_MIN - j)))   131    132         __raise_overflow_error();   133    134     /* Return the new integer. */   135     return __new_int(i + j);   136 }   137    138 __attr __fn_native__int_sub(__attr __args[])   139 {   140     __attr * const _data = &__args[1];   141     __attr * const other = &__args[2];   142     /* _data and other interpreted as int */   143     int i = _data->intvalue;   144     int j = other->intvalue;   145    146     /* Test for overflow. */   147     if (((i < 0) && (j > 0) && (i < INT_MIN + j)) ||   148         ((i > 0) && (j < 0) && (i > INT_MAX + j)))   149    150         __raise_overflow_error();   151    152     /* Return the new integer. */   153     return __new_int(i - j);   154 }   155    156 __attr __fn_native__int_mul(__attr __args[])   157 {   158     __attr * const _data = &__args[1];   159     __attr * const other = &__args[2];   160     /* _data and other interpreted as int */   161     int i = _data->intvalue;   162     int j = other->intvalue;   163    164     /* Test for overflow. */   165     if (((i > 0) && (j > 0) && (i > INT_MAX / j)) ||   166         ((i < 0) && (j < 0) && (i > INT_MAX / j)) ||   167         ((i < 0) && (j > 0) && (i < INT_MIN / j)) ||   168         ((i > 0) && (j < 0) && (j < INT_MIN / i)))   169    170         __raise_overflow_error();   171    172     /* Return the new integer. */   173     return __new_int(i * j);   174 }   175    176 __attr __fn_native__int_div(__attr __args[])   177 {   178     __attr * const _data = &__args[1];   179     __attr * const other = &__args[2];   180     /* _data and other interpreted as int */   181     int i = _data->intvalue;   182     int j = other->intvalue;   183    184     /* Test for division by zero or overflow. */   185     if (j == 0)   186         __raise_zero_division_error();   187     else if ((j == -1) && (i == INT_MIN))   188         __raise_overflow_error();   189    190     /* Return the new integer. */   191     return __new_int(i / j);   192 }   193    194 __attr __fn_native__int_mod(__attr __args[])   195 {   196     __attr * const _data = &__args[1];   197     __attr * const other = &__args[2];   198     /* _data and other interpreted as int */   199     int i = _data->intvalue;   200     int j = other->intvalue;   201    202     /* Test for division by zero or overflow. */   203     if (j == 0)   204         __raise_zero_division_error();   205     else if ((j == -1) && (i == INT_MIN))   206         __raise_overflow_error();   207    208     /* Return the new integer. */   209     return __new_int(i % j);   210 }   211    212 __attr __fn_native__int_neg(__attr __args[])   213 {   214     __attr * const _data = &__args[1];   215     /* _data interpreted as int */   216     int i = _data->intvalue;   217    218     /* Test for overflow. */   219     if (i == INT_MIN)   220         __raise_overflow_error();   221    222     /* Return the new integer. */   223     return __new_int(-i);   224 }   225    226 __attr __fn_native__int_pow(__attr __args[])   227 {   228     __attr * const _data = &__args[1];   229     __attr * const other = &__args[2];   230     /* _data and other interpreted as int */   231     int i = _data->intvalue;   232     int j = other->intvalue;   233     int k;   234    235     errno = 0;   236     k = (int) pow(i, j);   237    238     /* Test for overflow. */   239    240     if (errno == ERANGE)   241         __raise_overflow_error();   242    243     /* Return the new integer. */   244     return __new_int(k);   245 }   246    247 __attr __fn_native__int_and(__attr __args[])   248 {   249     __attr * const _data = &__args[1];   250     __attr * const other = &__args[2];   251     /* _data and other interpreted as int */   252     int i = _data->intvalue;   253     int j = other->intvalue;   254    255     /* Return the new integer. */   256     /* NOTE: No overflow test applied. */   257     return __new_int(i & j);   258 }   259    260 __attr __fn_native__int_not(__attr __args[])   261 {   262     __attr * const _data = &__args[1];   263     /* _data interpreted as int */   264     int i = _data->intvalue;   265    266     /* Return the new integer. */   267     return __new_int(~i);   268 }   269    270 __attr __fn_native__int_or(__attr __args[])   271 {   272     __attr * const _data = &__args[1];   273     __attr * const other = &__args[2];   274     /* _data and other interpreted as int */   275     int i = _data->intvalue;   276     int j = other->intvalue;   277    278     /* Return the new integer. */   279     /* NOTE: No overflow test applied. */   280     return __new_int(i | j);   281 }   282    283 __attr __fn_native__int_xor(__attr __args[])   284 {   285     __attr * const _data = &__args[1];   286     __attr * const other = &__args[2];   287     /* _data and other interpreted as int */   288     int i = _data->intvalue;   289     int j = other->intvalue;   290    291     /* Return the new integer. */   292     /* NOTE: No overflow test applied. */   293     return __new_int(i ^ j);   294 }   295    296 __attr __fn_native__int_lt(__attr __args[])   297 {   298     __attr * const _data = &__args[1];   299     __attr * const other = &__args[2];   300     /* _data and other interpreted as int */   301     int i = _data->intvalue;   302     int j = other->intvalue;   303    304     /* Return a boolean result. */   305     return i < j ? __builtins___boolean_True : __builtins___boolean_False;   306 }   307    308 __attr __fn_native__int_gt(__attr __args[])   309 {   310     __attr * const _data = &__args[1];   311     __attr * const other = &__args[2];   312     /* _data and other interpreted as int */   313     int i = _data->intvalue;   314     int j = other->intvalue;   315    316     /* Return a boolean result. */   317     return i > j ? __builtins___boolean_True : __builtins___boolean_False;   318 }   319    320 __attr __fn_native__int_eq(__attr __args[])   321 {   322     __attr * const _data = &__args[1];   323     __attr * const other = &__args[2];   324     /* _data and other interpreted as int */   325     int i = _data->intvalue;   326     int j = other->intvalue;   327    328     /* Return a boolean result. */   329     return i == j ? __builtins___boolean_True : __builtins___boolean_False;   330 }   331    332 __attr __fn_native__int_ne(__attr __args[])   333 {   334     __attr * const _data = &__args[1];   335     __attr * const other = &__args[2];   336     /* _data and other interpreted as int */   337     int i = _data->intvalue;   338     int j = other->intvalue;   339    340     /* Return a boolean result. */   341     return i != j ? __builtins___boolean_True : __builtins___boolean_False;   342 }   343    344 __attr __fn_native__int_str(__attr __args[])   345 {   346     __attr * const _data = &__args[1];   347     /* _data interpreted as int */   348     int i = _data->intvalue;   349     /* Employ a buffer big enough to fit the largest integer plus an extra   350        character, a minus sign, and the null terminator. */   351     unsigned int n = (int) log10(INT_MAX) + 3;   352     char *s = (char *) __ALLOCATE(n, sizeof(char));   353    354     snprintf(s, n, "%d", i);   355    356     /* Return a new string. */   357     return __new_str(s);   358 }   359    360 __attr __fn_native__str_add(__attr __args[])   361 {   362     __attr * const _data = &__args[1];   363     __attr * const other = &__args[2];   364     /* _data, other interpreted as string */   365     char *s = _data->strvalue;   366     char *o = other->strvalue;   367     int n = strlen(s) + strlen(o) + 1;   368     char *r = (char *) __ALLOCATE(n, sizeof(char));   369    370     strncpy(r, s, n);   371     strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */   372    373     /* Return a new string. */   374     return __new_str(r);   375 }   376    377 __attr __fn_native__str_lt(__attr __args[])   378 {   379     __attr * const _data = &__args[1];   380     __attr * const other = &__args[2];   381     /* _data, other interpreted as string */   382     char *s = _data->strvalue;   383     char *o = other->strvalue;   384    385     /* NOTE: Using simple byte-level string operations. */   386     return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False;   387 }   388    389 __attr __fn_native__str_gt(__attr __args[])   390 {   391     __attr * const _data = &__args[1];   392     __attr * const other = &__args[2];   393     /* _data, other interpreted as string */   394     char *s = _data->strvalue;   395     char *o = other->strvalue;   396    397     /* NOTE: Using simple byte-level string operations. */   398     return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False;   399 }   400    401 __attr __fn_native__str_eq(__attr __args[])   402 {   403     __attr * const _data = &__args[1];   404     __attr * const other = &__args[2];   405     /* _data, other interpreted as string */   406     char *s = _data->strvalue;   407     char *o = other->strvalue;   408    409     /* NOTE: Using simple byte-level string operations. */   410     return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False;   411 }   412    413 __attr __fn_native__str_len(__attr __args[])   414 {   415     __attr * const _data = &__args[1];   416     /* _data interpreted as string */   417     char *s = _data->strvalue;   418    419     /* Return the new integer. */   420     return __new_int(strlen(s));   421 }   422    423 __attr __fn_native__str_nonempty(__attr __args[])   424 {   425     __attr * const _data = &__args[1];   426     /* _data interpreted as string */   427     char *s = _data->strvalue;   428    429     return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;   430 }   431    432 __attr __fn_native__str_ord(__attr __args[])   433 {   434     __attr * const _data = &__args[1];   435     /* _data interpreted as string */   436     char *s = _data->strvalue;   437    438     return __new_int((unsigned int) s[0]);   439 }   440    441 __attr __fn_native__str_substr(__attr __args[])   442 {   443     __attr * const _data = &__args[1];   444     __attr * const start = &__args[2];   445     __attr * const size = &__args[3];   446     /* _data interpreted as string */   447     char *s = _data->strvalue, *sub;   448     /* start.__data__ interpreted as int */   449     int i = __load_via_object(start->value, __pos___data__).intvalue;   450     /* size.__data__ interpreted as int */   451     int l = __load_via_object(size->value, __pos___data__).intvalue;   452    453     /* Reserve space for a new string. */   454     sub = (char *) __ALLOCATE(l + 1, sizeof(char));   455     strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */   456     return __new_str(sub);   457 }   458    459 __attr __fn_native__list_init(__attr __args[])   460 {   461     __attr * const size = &__args[1];   462     /* size.__data__ interpreted as int */   463     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   464     __attr attr = {0, .seqvalue=__new_fragment(n)};   465    466     /* Return the __data__ attribute. */   467     return attr;   468 }   469    470 __attr __fn_native__list_setsize(__attr __args[])   471 {   472     __attr * const _data = &__args[1];   473     __attr * const size = &__args[2];   474     /* _data interpreted as list */   475     __fragment *data = _data->seqvalue;   476     /* size.__data__ interpreted as int */   477     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   478    479     data->size = n;   480     return __builtins___none_None;   481 }   482    483 __attr __fn_native__list_append(__attr __args[])   484 {   485     __attr * const self = &__args[1];   486     __attr * const value = &__args[2];   487     /* self.__data__ interpreted as list */   488     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   489     __fragment *newdata = __fragment_append(data, value);   490    491     /* Replace the __data__ attribute if appropriate. */   492     if (newdata != data)   493         __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));   494     return __builtins___none_None;   495 }   496    497 __attr __fn_native__list_concat(__attr __args[])   498 {   499     __attr * const self = &__args[1];   500     __attr * const other = &__args[2];   501     /* self.__data__, other interpreted as list */   502     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   503     __fragment *other_data = other->seqvalue;   504     __fragment *newdata = data;   505     unsigned int size = data->size, capacity = data->capacity;   506     unsigned int other_size = other_data->size;   507     unsigned int i, j, n;   508    509     /* Re-allocate the fragment if the capacity has been reached. */   510     if (size + other_size >= capacity)   511     {   512         n = size + other_size;   513         newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));   514         newdata->capacity = n;   515     }   516    517     /* Copy the elements from the other list and increment the list size. */   518     for (i = size, j = 0; j < other_size; i++, j++)   519         newdata->attrs[i] = other_data->attrs[j];   520     newdata->size = n;   521    522     /* Replace the __data__ attribute if appropriate. */   523     if (newdata != data)   524         __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));   525     return __builtins___none_None;   526 }   527    528 __attr __fn_native__list_len(__attr __args[])   529 {   530     __attr * const _data = &__args[1];   531     /* _data interpreted as fragment */   532     unsigned int size = _data->seqvalue->size;   533    534     /* Return the new integer. */   535     return __new_int(size);   536 }   537    538 __attr __fn_native__list_nonempty(__attr __args[])   539 {   540     __attr * const _data = &__args[1];   541    542     return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False;   543 }   544    545 __attr __fn_native__list_element(__attr __args[])   546 {   547     __attr * const _data = &__args[1];   548     __attr * const index = &__args[2];   549     /* _data interpreted as fragment */   550     __attr *elements = _data->seqvalue->attrs;   551     /* index.__data__ interpreted as int */   552     int i = __load_via_object(index->value, __pos___data__).intvalue;   553    554     return elements[i];   555 }   556    557 __attr __fn_native__list_setelement(__attr __args[])   558 {   559     __attr * const _data = &__args[1];   560     __attr * const index = &__args[2];   561     __attr * const value = &__args[3];   562     /* _data interpreted as fragment */   563     __attr *elements = _data->seqvalue->attrs;   564     /* index.__data__ interpreted as int */   565     int i = __load_via_object(index->value, __pos___data__).intvalue;   566    567     /* Set the element. */   568     elements[i] = *value;   569     return __builtins___none_None;   570 }   571    572 __attr __fn_native__buffer_str(__attr __args[])   573 {   574     __attr * const _data = &__args[1];   575     /* _data interpreted as buffer */   576     __fragment *data = _data->seqvalue;   577     unsigned int size = 0, i, j, n;   578     char *s, *o;   579    580     /* Calculate the size of the string. */   581     for (i = 0; i < data->size; i++)   582         size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);   583    584     /* Reserve space for a new string. */   585     s = (char *) __ALLOCATE(size + 1, sizeof(char));   586    587     /* Build a single string from the buffer contents. */   588     for (i = 0, j = 0; i < data->size; i++)   589     {   590         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   591         n = strlen(o);   592         strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */   593         j += n;   594     }   595    596     /* Return a new string. */   597     return __new_str(s);   598 }   599    600 __attr __fn_native__get_using(__attr __args[])   601 {   602     __attr * const callable = &__args[1];   603     __attr * const instance = &__args[2];   604    605     return __replace_context(instance->value, *callable);   606 }   607    608 __attr __fn_native__object_getattr(__attr __args[])   609 {   610     __attr * const obj = &__args[1];   611     __attr * const name = &__args[2];   612     __attr * const _default = &__args[3];   613    614     /* NOTE: To be written. */   615     return __builtins___none_None;   616 }   617    618 static int __issubclass(__ref obj, __attr cls)   619 {   620     return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));   621 }   622    623 __attr __fn_native__isinstance(__attr __args[])   624 {   625     __attr * const obj = &__args[1];   626     __attr * const cls = &__args[2];   627    628     /* cls must be a class. */   629     if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))   630         return __builtins___boolean_True;   631     else   632         return __builtins___boolean_False;   633 }   634    635 __attr __fn_native__issubclass(__attr __args[])   636 {   637     __attr * const obj = &__args[1];   638     __attr * const cls = &__args[2];   639    640     /* obj and cls must be classes. */   641     if (__issubclass(obj->value, *cls))   642         return __builtins___boolean_True;   643     else   644         return __builtins___boolean_False;   645 }   646    647 /* Input/output. */   648    649 __attr __fn_native__fdopen(__attr __args[])   650 {   651     __attr * const fd = &__args[1];   652     __attr * const mode = &__args[2];   653     /* fd.__data__ interpreted as int */   654     int i = __load_via_object(fd->value, __pos___data__).intvalue;   655     /* str.__data__ interpreted as string */   656     char *s = __load_via_object(mode->value, __pos___data__).strvalue;   657     FILE *f;   658     __attr attr;   659    660     errno = 0;   661     f = fdopen(i, s);   662    663     /* Produce an exception if the operation failed. */   664    665     if (f == NULL)   666         __raise_io_error(__new_int(errno));   667    668     /* Return the __data__ attribute. */   669    670     else   671     {   672         attr.context = 0;   673         attr.datavalue = (void *) f;   674         return attr;   675     }   676 }   677    678 __attr __fn_native__fread(__attr __args[])   679 {   680     __attr * const fp = &__args[1];   681     __attr * const size = &__args[2];   682     /* fp interpreted as FILE reference */   683     FILE *f = (FILE *) fp->datavalue;   684     /* size.__data__ interpreted as int */   685     int to_read = __load_via_object(size->value, __pos___data__).intvalue;   686     char buf[to_read];   687     size_t have_read;   688     int error;   689     char *s;   690    691     have_read = fread(buf, sizeof(char), to_read, f);   692    693     if (have_read != to_read)   694     {   695         if (feof(f))   696             __raise_eof_error();   697         else if (error = ferror(f))   698             __raise_io_error(__new_int(error));   699     }   700    701     /* Reserve space for a new string. */   702    703     s = __ALLOCATE(have_read + 1, sizeof(char));   704     strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   705     return __new_str(s);   706 }   707    708 __attr __fn_native__fwrite(__attr __args[])   709 {   710     __attr * const fp = &__args[1];   711     __attr * const str = &__args[2];   712     /* fp interpreted as FILE reference */   713     FILE *f = (FILE *) fp->datavalue;   714     /* str.__data__ interpreted as string */   715     char *s = __load_via_object(str->value, __pos___data__).strvalue;   716     size_t to_write = strlen(s);   717     size_t have_written = fwrite(s, sizeof(char), to_write, f);   718     int error;   719    720     if (have_written != to_write)   721     {   722         if (feof(f))   723             __raise_eof_error();   724         else if (error = ferror(f))   725             __raise_io_error(__new_int(error));   726     }   727    728     return __builtins___none_None;   729 }   730    731 __attr __fn_native__read(__attr __args[])   732 {   733     __attr * const fd = &__args[1];   734     __attr * const n = &__args[2];   735     /* fd.__data__ interpreted as int */   736     int i = __load_via_object(fd->value, __pos___data__).intvalue;   737     /* n.__data__ interpreted as int */   738     int to_read = __load_via_object(n->value, __pos___data__).intvalue;   739     char buf[to_read];   740     ssize_t have_read;   741     char *s;   742    743     errno = 0;   744     have_read = read(i, buf, to_read * sizeof(char));   745    746     if (have_read == -1)   747         __raise_io_error(__new_int(errno));   748     else   749     {   750         /* Reserve space for a new string. */   751    752         s = __ALLOCATE(have_read + 1, 1);   753         strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */   754         return __new_str(s);   755     }   756 }   757    758 __attr __fn_native__write(__attr __args[])   759 {   760     __attr * const fd = &__args[1];   761     __attr * const str = &__args[2];   762     /* fd.__data__ interpreted as int */   763     int i = __load_via_object(fd->value, __pos___data__).intvalue;   764     /* str.__data__ interpreted as string */   765     char *s = __load_via_object(str->value, __pos___data__).strvalue;   766    767     write(i, s, sizeof(char) * strlen(s));   768     return __builtins___none_None;   769 }   770    771 /* Module initialisation. */   772    773 void __main_native()   774 {   775 }