#include <stdio.h>

// A suggested mechanism for translating strings (and string parameters) to C...

// perms.h would declare all lengths of string as different struct types:
typedef struct string string;
typedef struct string255 string255;
// ...
typedef struct string12 string12;
// ...
typedef struct string0 string0;


struct string {                                                             // %string (*)
  union {
    struct { char length; char s[255]; };
    char charno[256]; // can add an extra byte if 100% compatibility not forced, and we want easy C compatibility with a \0 after a 255 char string.
    struct string255 {                                                      // %string (255)
      union { struct { char length; char s[255]; }; char charno[256]; };
    } s255;
    // ...
    struct string12 {                                                       // %string (12)
      union { struct { char length; char s[12]; }; char charno[128]; };
    } s12;
    // ...
    struct string1 {                                                        // %string (1)
      union { struct { char length; char s[1]; }; char charno[2]; };
    } s1;
    struct string0 {                                                        // ( for empty string "" if needed? )
      union { struct { char length; char s[0]; }; char charno[1]; };
    } s0;
  };
};


void printstring(string *Q_ptr) {        // Imp would declare %routine printstring(%string(255) Q) but i2c would map it as if it were %routine printstring(%string(255)%name Q)
  string Q = *(string *) Q_ptr;          // and make the mutable copy inside the procedure rather than passing the string on the stack...
  fprintf(stdout, "%s\n", Q.s);          // and if the string were not written to, we could optimise the procedure by only using the pointer and omiting the copy.
}

int main(int argc, char **argv) {
  
  // %string (12) Message = "hello world"
  string12 Message = {.s="hello world!"};   // only 13 bytes would be allocated.  (My prototype used 256 bytes for all strings)

  // LENGTH(Message) = 5; (or equivalently, "CHARNO(Message, 0) = 5;")
  Message.length = 5;   /* and only in this example for easy C compatibiilty: */ Message.s[Message.length] = '\0';

  // CHARNO(Message, 1) = 'H';
  Message.charno[1] = 'H';
  
  printstring((string *)&Message);  // string values are passed as pointers. (ERCC compilers did this too...)
  return 0;
}
