pike.git / lib / modules / Tools.pmod / Standalone.pmod / precompile.pike

version» Context lines:

pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:4:   #error Pike binary is too old to be used for precompile.   #error At least 7.8 is required.   #endif      #pike __REAL_VERSION__      #define TOSTR(X) #X   #define DEFINETOSTR(X) TOSTR(X)      #if constant(Pike.__HAVE_CPP_PREFIX_SUPPORT__) - constant precompile_api_version = "5"; + constant precompile_api_version = "6";   #else   constant precompile_api_version = "3";   #endif      constant want_args = 1;    - constant description = "Converts .pmod-files to .c files"; + //! Convert .cmod-files to .c files. +  + constant description = "Converts .cmod-files to .c files"; +  + mapping map_types = ([]), need_obj_defines = ([]); +    string usage = #"[options] <from> > <to>          This script is used to process *.cmod files into *.c files, it    reads Pike style prototypes and converts them into C code.       Supported options are:       -h,--help Display this help text.       -v,--version Display the API version.    -  +  --api Set the API version. +  +  -b,--base Set the base name for the file. +  +  -o,--out Set the output filename. +  +  -w,--warnings Enable warnings. +     The input can look something like this:       DECLARATIONS       PIKECLASS fnord    attributes;    {    INHERIT bar    attributes;   
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:126:    out. This applies to the int and float runtime types, but not    for the special case \"void|zero\".       Note: If a function argument accepts more than one runtime type, e.g.    \"int|string\", then no type checking at all is performed on the svalue. That    is not a bug - the user code has to do a type check later anyway, and it's    more efficient to add the error handling there.       Currently, the following attributes are understood:    efun; makes this function a global constant (no value) +  export; Declare the corresponding C-symbol PMOD_EXPORT.    flags; ID_STATIC | ID_NOMASK etc.    optflags; OPT_TRY_OPTIMIZE | OPT_SIDE_EFFECT etc.    optfunc; Optimization function.    type; Override the pike type in the prototype with this type.    FIXME: this doesn't quite work    rawtype; Override the pike type in the prototype with this C-code    type, e.g. tInt, tMix etc.    errname; The name used when throwing errors.    name; The name used when doing add_function. -  +  c_name; The name to use for a PIKEVAR in a C struct.    prototype; Ignore the function body, just add a prototype entry.    program_flags; PROGRAM_USES_PARENT | PROGRAM_DESTRUCT_IMMEDIATE etc.    gc_trivial; Only valid for EXIT functions. This instructs the gc that    the EXIT function is trivial and that it's ok to destruct    objects of this program in any order. In general, if there    is an EXIT function, the gc has to take the same care as if -  there is a destroy function. But if the EXIT function +  there is a _destruct function. But if the EXIT function    doesn't mind that arbitrary referenced pike objects gets    destructed before this one (a very common trait since most    EXIT functions only do simple cleanup), then this attribute    can be added to make the gc work a little easier.       POLYMORPHIC FUNCTION OVERLOADING    You can define the same function several times with different    types. This program will select the proper function whenever    possible.   
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:188:   void warn(string s, mixed ... args)   {    if (warnings) {    if (sizeof(args)) s = sprintf(s, @args);    werror(s);    return;    }    error(s, @args);   }    + array global_declarations=({}); + multiset check_used = (<>);      /* Strings declared with MK_STRING. */   mapping(string:string) strings = ([    // From stralloc.h:    "":"empty_pike_string",       // From program.h:    "this_program":"this_program_string", -  +  "this":"this_string",    // lfuns:    "__INIT":"lfun_strings[LFUN___INIT]",    "create":"lfun_strings[LFUN_CREATE]", -  "destroy":"lfun_strings[LFUN_DESTROY]", +  "_destruct":"lfun_strings[LFUN__DESTRUCT]",    "`+":"lfun_strings[LFUN_ADD]",    "`-":"lfun_strings[LFUN_SUBTRACT]",    "`&":"lfun_strings[LFUN_AND]",    "`|":"lfun_strings[LFUN_OR]",    "`^":"lfun_strings[LFUN_XOR]",    "`<<":"lfun_strings[LFUN_LSH]",    "`>>":"lfun_strings[LFUN_RSH]",    "`*":"lfun_strings[LFUN_MULTIPLY]",    "`/":"lfun_strings[LFUN_DIVIDE]",    "`%":"lfun_strings[LFUN_MOD]",
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:243:    "``/":"lfun_strings[LFUN_RDIVIDE]",    "``%":"lfun_strings[LFUN_RMOD]",    "`+=":"lfun_strings[LFUN_ADD_EQ]",    "_is_type":"lfun_strings[LFUN__IS_TYPE]",    "_sprintf":"lfun_strings[LFUN__SPRINTF]",    "_equal":"lfun_strings[LFUN__EQUAL]",    "_m_delete":"lfun_strings[LFUN__M_DELETE]",    "_get_iterator":"lfun_strings[LFUN__GET_ITERATOR]",    "`[..]":"lfun_strings[LFUN_RANGE]",    "_search":"lfun_strings[LFUN__SEARCH]", +  "_types":"lfun_strings[LFUN__TYPES]", +  "_serialize":"lfun_strings[LFUN__SERIALIZE]", +  "_deserialize":"lfun_strings[LFUN__DESERIALIZE]", +  "_size_object":"lfun_strings[LFUN__SIZE_OBJECT]", +  "_random":"lfun_strings[LFUN__RANDOM]", +  "`**":"lfun_strings[LFUN_POW]", +  "``**":"lfun_strings[LFUN_RPOW]", +  "_sqrt":"lfun_strings[LFUN__SQRT]",   ]);   int last_str_id = 0;   array(string) stradd = ({});   int last_svalue_id = 0;   mapping(string:string) svalues = ([]);      string parse_string(string str)   {    if (search(str, "\\") == -1) {    return str[1..sizeof(str)-2];
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:337:    case "object":    case "program":    case "function":    case "mapping":    case "array":    case "multiset":    case "int":    case "type":    case "string":    if(arrayp(t[p])) p++; +  case "utf8_string": +  case "sprintf_format": +  case "sprintf_args":    case "bignum":    case "longest":    case "float":    break;    }    }    break;    }    switch( arrayp(t[p]) ? "" : (string) t[p])    {
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:392:    }    }    ret+=n;    if(ret[0]=='_' || (ret[0]>='0' && ret[0]<='9'))    ret="cq_"+ret;    return ret;   }         /* -  * This function maps C types to the approperiate -  * pike type. Input and outputs are arrays of tokens +  * This function maps C types to the appropriate +  * pike type. It is used by the CTYPE syntax. +  * +  * @param tokens +  * An array of C tokens representing the C type. +  * +  * @returns +  * Returns the corresponding Pike type.    */ - PikeType convert_ctype(array tokens) + PikeType convert_ctype(array(PC.Token) tokens)   { -  switch((string)tokens[0]) -  { +  int signed = 1; +  +  while (1) { +  switch((string)tokens[0]) { +  case "unsigned": +  signed = 0; +  tokens = tokens[1..]; +  if (!sizeof(tokens)) +  return PikeType("int(0..)"); +  break; +  +  case "signed": +  signed = 1; +  tokens = tokens[1..]; +  if (!sizeof(tokens)) +  return PikeType("int"); +  break; +     case "char": /* char* */    if(sizeof(tokens) >1 && "*" == (string)tokens[1]) -  return PikeType("string"); +  return PikeType("string(8bit)"); +  else if (signed) +  return PikeType("int(-128..127)"); +  else +  return PikeType("int(8bit)");       case "short": -  +  if (signed) +  return PikeType("int(-32768..32767)"); +  else +  return PikeType("int(16bit)"); +     case "int":    case "long": -  +  case "INT32": +  if (signed) return PikeType("int"); +  return PikeType("int(0..)"); +     case "size_t": -  +  return PikeType("int(0..)"); +     case "ptrdiff_t": -  case "INT32": +     return PikeType("int");       case "double":    case "float":    return PikeType("float");       default:    error("Unknown C type.\n");    }    } -  + }      string stringify(string s)   {    return sprintf("\"%{\\%o%}\"",(array)s);   // return sprintf("%O",s);   }      class PikeType   {    PC.Token t;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:514:    case "1":    case "2":    case "3":    case "4":    case "5":    case "6":    case "7":    case "8":    case "9":    case "bignum": +  case "sprintf_args":    return "mixed";       // FIXME: Guess the special "longest" type ought to be    // "CTYPE LONGEST" instead, but the CTYPE stuff seems to be    // broken and I don't want to dig into it.. /mast    case "longest": return "LONGEST";       case "int":    case "float":    case "string":
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:536:    case "array":    case "mapping":    case "multiset":    case "type":    case "program":    case "mixed":    case "void":    case "zero":    return ret;    +  case "utf8_string": +  case "sprintf_format": +  return "string"; +     default: return "object";    }    }       string realtype()    /* Similar to basetype, but returns the source description if the    * base type. */    {    string ts = (string) t;    switch (ts) {
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:584:    case "1":    case "2":    case "3":    case "4":    case "5":    case "6":    case "7":    case "8":    case "9":    +  case "sprintf_args":    case "mixed":    return ({    "int",    "float",    "string",    "object",    "program",    "function",    "array",    "mapping",
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:617:    case "object":    case "function":    case "array":    case "mapping":    case "multiset":    case "type":    case "void":    case "zero":    return ({ ret });    +  case "utf8_string": +  case "sprintf_format": +  return ({ "string" }); +     case "bignum":    case "longest":    return ({"int", "object"});       default: return ({ "object" });    }    }          /*
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:677:    {    case "void": return "void";    case "zero":    return may_be_void()?"struct svalue *":"INT_TYPE";    case "int":    return (may_be_void_or_zero (1, 2) == 1 ?    "struct svalue *" : "INT_TYPE");    case "float":    return (may_be_void_or_zero (1, 2) == 1 ?    "struct svalue *" : "FLOAT_TYPE"); +  case "utf8_string": case "sprintf_format":    case "string": return "struct pike_string *";       case "array":    case "multiset":    case "mapping":       case "object":    case "program": return "struct "+btype+" *";       case "type": return "struct pike_type *";       case "function":    case "mixed":    case "bignum": -  +  case "sprintf_args":    if (is_struct_entry) {    return "struct svalue";    } else {    return "struct svalue *";    }       case "longest":    return "LONGEST";       default:
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:783:    case "6":    case "7":    case "8":    case "9": return sprintf("tVar(%s)",ret);       case "zero": return "tZero";    case "void": return "tVoid";    case "float": return "tFloat";    case "string":    { -  int low = (int)(string)(args[0]->t); -  int high = (int)(string)(args[1]->t); +  // Clamp the integer range to 32 bit signed. +  int low = limit(-0x80000000, (int)(string)(args[0]->t), 0x7fffffff); +  int high = limit(-0x80000000, (int)(string)(args[1]->t), 0x7fffffff); +  if (high < low) +  exit(1, "Error: Inversed range in integer type, string(%s..%s).\n", +  (string)args[0]->t, (string)args[1]->t); +     if (!low) {    switch(high) {    case 0x0000: return "tStr0";    case 0x007f: return "tStr7";    case 0x00ff: return "tStr8";    case 0xffff: return "tStr16";    }    } else if ((low == -0x80000000) && (high == 0x7fffffff)) {    return "tStr";    } -  +  // NOTE! This piece of code KNOWS that the serialized +  // value of PIKE_T_INT is 8!    return sprintf("tNStr(%s)",    stringify(sprintf("\010%4c%4c", low, high)));    } -  +  case "utf8_string": return "tUtf8Str"; +  case "sprintf_format": return "tAttr(\"sprintf_format\", tStr)"; +  case "sprintf_args": return "tAttr(\"sprintf_args\", tMix)";    case "program": return "tPrg(tObj)";    case "any": return "tAny";    case "mixed": return "tMix";    case "int": -  +  // Clamp the integer range to 32 bit signed. +  int low = limit(-0x80000000, (int)(string)(args[0]->t), 0x7fffffff); +  int high = limit(-0x80000000, (int)(string)(args[1]->t), 0x7fffffff); +  if (high < low) +  exit(1, "Error: Inversed range in integer type, int(%s..%s).\n", +  (string)args[0]->t, (string)args[1]->t); +     // NOTE! This piece of code KNOWS that PIKE_T_INT is 8! -  return stringify(sprintf("\010%4c%4c", -  (int)(string)(args[0]->t), -  (int)(string)(args[1]->t))); +  return stringify(sprintf("\010%4c%4c", low, high));       case "bignum":    case "longest":    return "tInt";    -  case "object": return "tObj"; +  case "object": +  return "tObj";    default: -  +  string define = "tObjImpl_"+replace(upper_case(ret), ".", "_"); +  if( !need_obj_defines[define] ) +  need_obj_defines[define] = ret;    return sprintf("tName(%O, tObjImpl_%s)",    ret, replace(upper_case(ret), ".", "_"));    }    }          /*    * Output pike type, such as array(int)    */    string output_pike_type(int pri)
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:872:    return "function";    return ret;       case "=":    return sprintf("%s=%s",    args[0]->output_pike_type(0),    args[1]->output_pike_type(0));       case "int":    case "string": +  // Clamp the integer range to 32 bit signed. +  int low = limit(-0x80000000, (int)(string)(args[0]->t), 0x7fffffff); +  int high = limit(-0x80000000, (int)(string)(args[1]->t), 0x7fffffff); +  if (!low && !(high & (high + 1))) { +  if (!high) { +  if (ret == "int") return "zero"; +  return sprintf("%s(zero)", ret); +  } +  +  int i; +  for (i = 0; high; high >>= 1, i++) +  ; +  return sprintf("%s(%dbit)", ret, i); +  }    ret=sprintf("%s(%s..%s)",    ret,    args[0]->t == "-2147483648" ? "" : args[0]->t,    args[1]->t == "2147483647" ? "" : args[1]->t);    if(has_suffix(ret, "(..)")) return ret[..sizeof(ret)-5];    return ret;    -  +  case "utf8_string": +  return "utf8_string"; +  +  case "sprintf_format": +  return "string"; +  +  case "sprintf_args": +  return "mixed"; +     case "bignum":    case "longest":    return "int";       default:    return ret;    }    }      
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1080:    return;       case "int":    case "string":    string low = (string)(int)-0x80000000;    string high = (string)0x7fffffff;       if(arrayp(q=tok[1]))    {    tmp=q[1..sizeof(q)-2]/({".."}); -  /* Workaround for buggy Parser.Pike */ -  if(sizeof(tmp)==1) tmp=q[1..sizeof(q)-2]/({".. "}); -  if (sizeof(tmp) == 1) { +  if(sizeof(tmp)==1) +  {    int bits;    /* Support the string(Xbit) syntax too. */ -  if ((sizeof(q) == 4) && (q[2]->cast("string") == "bit") && -  ((bits = (int)q[1]->cast("string")) > 0)) { +  if (sizeof(q) == 3 && sscanf((string)q[1], "%dbit", bits)) +  {    low = "0";    high = sprintf("%d", (1 << bits) - 1); -  } else { -  error("Syntax error in string subtype.\n"); +     } -  +  else if (sizeof(q) == 4 && q[2] == "bit") +  { +  // Parser.Pike from Pike 8.1.3 or earlier. +  low = "0"; +  high = sprintf("%d", (1 << (int)(string)q[1]) - 1); +  } +  else +  { +  werror("%s:%d: Syntax error: %s is not a valid type.\n", +  t->file, t->line, merge(tok)); +  exit(1); +  }    } else { -  if(sizeof(tmp[0])) low=tmp[0]->cast("string")*""; -  if(sizeof(tmp[1])) high=tmp[1]->cast("string")*""; +  if(sizeof(tmp[0])) low=(array(string))tmp[0]*""; +  if(sizeof(tmp[1])) high=(array(string))tmp[1]*"";    }    }    args=({PikeType(PC.Token(low)),PikeType(PC.Token(high))});    break;       case "object":    case "type":    if (arrayp(tok[1]) && sizeof(tok[1]) > 2) {    if ((sizeof(tok[1]) > 3) && (api < 3)) {    // Make sure that the user specifies
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1131:   class CType {    inherit PikeType;    string ctype;       string output_c_type() { return ctype; }    void create(string _ctype) {    ctype = _ctype;    }   }    + // Used to find the declared upper and lower range for strings + // in argument types. + array(int) clamp_int_range(PikeType complex_type, string ranged_type) + { +  switch((string)complex_type->t) { +  case "|": +  { +  array(int) res = UNDEFINED; +  foreach(complex_type->args, PikeType arg) { +  array(int) sub_res = clamp_int_range(arg, ranged_type); +  if (!sub_res) continue; +  if (!res) { +  res = sub_res; +  continue; +  } +  if (res[0] > sub_res[0]) res[0] = sub_res[0]; +  if (res[1] < sub_res[1]) res[1] = sub_res[1]; +  } +  return res; +  } +  case "&": +  { +  array(int) res = ({ -0x80000000, 0x7fffffff }); +  foreach(complex_type->args, PikeType arg) { +  array(int) sub_res = clamp_int_range(arg, ranged_type); +  if (!sub_res) return UNDEFINED; +  if (res[0] < sub_res[0]) res[0] = sub_res[0]; +  if (res[1] > sub_res[1]) res[1] = sub_res[1]; +  } +  if (res[0] > res[1]) return UNDEFINED; +  return res; +  } +  +  case "sprintf_format": +  return ({ -0x80000000, 0x7fffffff }); +  +  case "utf8_string": +  if (ranged_type == "string") { +  return ({ 0, 255 }); +  } +  // FALL_THROUGH +  default: +  if (((string)complex_type->t) == ranged_type) { +  array(PikeType) args = complex_type->args; +  if (sizeof(args) == 2) { +  return ({ limit(-0x80000000, +  (int)(string)(args[0]->t), +  0x7fffffff), +  limit(-0x80000000, +  (int)(string)(args[1]->t), +  0x7fffffff), +  }); +  } +  return ({ -0x80000000, 0x7fffffff }); +  } +  return UNDEFINED; +  } + } +    /*    * This class is used to represent one function argument    */   class Argument   {    /* internal */ -  string _name; -  PikeType _type; -  string _c_type; -  string _basetype; +  string _name; // Name of argument. +  PikeType _type; // Declared Pike type. +  int _line; // Line number in CMOD. +  string _file; // Filename of CMOD. +     int _is_c_type; -  int _line; -  string _file; -  string _typename; -  string _realtype; +     -  +  // The following are cached values. +  string _c_type; // _type->c_storage_type(). +  string _basetype; // _type->basetype(). +  string _typename; // Pretty-printed Pike type (used in error messages). +  string _realtype; // _type->realtype(). +     int is_c_type() { return _is_c_type; }    int may_be_void_or_zero (int may_be_void, int may_be_zero)    { return type()->may_be_void_or_zero (may_be_void, may_be_zero); }    int may_be_void() { return type()->may_be_void(); }    int line() { return _line; }    string name() { return _name; }    PikeType type() { return _type; }       string basetype()    {
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1182:       string typename()    {    if(_typename) return _typename;    return _typename=    type()->copy_and_strip_type_assignments (1)->output_pike_type(0);    }       void create(array x)    { +  PC.Token t; +  if( arrayp(x[-1]) ) +  { +  // Nameless argument prototype +  t = x[0]; +  } +  else +  {    _name=(string)x[-1]; -  _file=x[-1]->file; -  _line=x[-1]->line; +  t = x[-1]; +  } +  _file=t->file; +  _line=t->line;    _type=PikeType(x[..sizeof(x)-2]);    }       string _sprintf(int how)    {    return type()->output_pike_type(0)+" "+name();    }   };      /*
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1292:    }    }       return func(ret, @args);   }      // FIXME: We could expand this to declare which attributes are valid   // where.   constant valid_attributes = (<    "efun", +  "export",    "flags",    "optflags",    "optfunc",    "type",    "rawtype",    "errname",    "name", -  +  "c_name", /* Override of generated C-symbol */    "prototype",    "program_flags",   >);      /*    * This function takes a list of tokens, containing attributes on the form:    * attributename foo bar gazonk ;    * attributename2 foo2 bar2 gazonk2 ;    *    * Returns a mapping like:
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1421:   class FuncData   {    string name;    string define;    PikeType type;    mapping attributes;    int max_args;    int min_args;    array(Argument) args;    -  string _sprintf() +  string _sprintf(int c)    {    return sprintf("FuncData(%s)",define);    }       int `==(mixed q)    {    return objectp(q) && q->name == name;   // return 0;    }   };
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1448: Inside #if defined(PRECOMPILE_OVERLOAD_DEBUG)
  #ifdef PRECOMPILE_OVERLOAD_DEBUG    werror("evaluate: %O\n",q);   #endif /* PRECOMPILE_OVERLOAD_DEBUG */    for(int e=0;e<sizeof(q);e++)    {    if(q[e] && sizeof(q[e]))    {    val++;    for(int d=e+1;d<sizeof(q);d++)    { -  if(!sizeof(q[e] ^ q[d])) /* equal is broken in some Pikes */ +  if(q[d] && !sizeof(q[e] ^ q[d])) /* equal is broken in some Pikes */    {   #ifdef PRECOMPILE_OVERLOAD_DEBUG    werror("EQ, %d %d\n",e,d);   #endif /* PRECOMPILE_OVERLOAD_DEBUG */    q[d]=0;    }    }    }    }    return val;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1630:       if(min_possible_arg == max_possible_arg)    argbase=(string) (-min_possible_arg);       out+=({PC.Token(sprintf("%*nswitch(TYPEOF(Pike_sp[%d%s])) {\n",    indent,    best_method,argbase)) });       mapping m=y[best_method];    mapping m2=m+([]); -  foreach(indices(m), string type) +  foreach(sort(indices(m)), string type)    {    array tmp=m[type];    if(tmp && sizeof(tmp))    { -  foreach(indices(m), string t2) +  foreach(sort(indices(m)), string t2)    {    if(equal(tmp, m[t2]) && !sizeof(tmp ^ m[t2]))    {    m_delete(m,t2);    out+=({PC.Token(sprintf("%*n case PIKE_T_%s:\n",    indent,    upper_case(t2)))});    }    }    out+=generate_overload_func_for(tmp,    indent+2,    min_possible_arg,    max_possible_arg,    name,    attributes);    }    }    out+=({    PC.Token(sprintf("%*n default:\n",indent)), -  PC.Token(sprintf("%*n SIMPLE_BAD_ARG_ERROR(%O,%d,%O);\n", +  PC.Token(sprintf("%*n SIMPLE_ARG_TYPE_ERROR(%O,%d,%O);\n",    indent,    attributes->errname || name,    best_method+1, -  indices(m2)*"|")), +  sort(indices(m2))*"|")),    PC.Token(sprintf("%*n}\n",indent)),    });    }    return out;   }    -  + int gid; +    // Parses a block of cmod code, separating it into declarations,   // functions to add, exit functions and other code.   class ParseBlock   {    array code=({});    array addfuncs=({});    array exitfuncs=({});    array declarations=({}); -  +  int local_id = ++gid;       void create(array(array|PC.Token) x, string base, string class_name)    {    array(array|PC.Token) ret=({});    array thestruct=({});       // FIXME: Consider generating code in the order it appears in    // the source file.    // /grubba 2004-12-10   
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1722:       string p;    string numid = "-1";    string offset = "0";    string indent = " ";    array pre = ({});    array post = ({});       mixed name=x[e+1];    string define=make_unique_name("inherit",name,base,"defined"); +  string inh_num = make_unique_name(base, name, "inh_num"); +  string inh_offset = make_unique_name(base, name, "inh_offset");    if ((string)name == "::") {    e++;    name = x[e+1];    if ((name == "this_program") &&    has_suffix(base, "_" + class_name)) {    define=make_unique_name("inherit",name,base,"defined"); -  +  inh_num = make_unique_name(base, name, "inh_num"); +  inh_offset = make_unique_name(base, name, "inh_offset");    name = UNDEFINED;    pre = ({    PC.Token(   sprintf(" do {\n"    " int i__ =\n"    " reference_inherited_identifier(Pike_compiler->previous, NULL,\n"    " %s);\n"    " if (i__ != -1) {\n"    " struct program *p = Pike_compiler->previous->new_program;\n"    " struct identifier *id__ = ID_FROM_INT(p, i__);\n"
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1800:    if (api < 5) {    warn("%s:%d: API level 5 (or higher) is required "    "for inherit of strings.\n",    name->file, name->line);    }    } else if (name) {    p = mkname((string)name, "program");    }    addfuncs +=    IFDEF(define, -  pre + ({ +  ({ +  PC.Token( +  sprintf(" %s = Pike_compiler->new_program->" +  "num_inherits;\n", +  inh_num), +  x[e]->line), +  }) + pre + ({    PC.Token(sprintf("%slow_inherit(%s, NULL, %s, "    "%s, %s, NULL);\n",    indent, p, numid, offset,    attributes->flags || "0"),    x[e]->line), -  +  PC.Token(sprintf("%s%s = Pike_compiler->new_program->" +  "inherits[%s].identifier_level;\n", +  indent, inh_offset, inh_num), +  x[e]->line),    }) + post); -  ret += DEFINE(define); +  ret += DEFINE(define) + ({ +  PC.Token(sprintf("static int %s = -1;\n", inh_num), +  x[e]->line), +  PC.Token(sprintf("static int %s = -1;\n", inh_offset), +  x[e]->line), +  });    e = pos;    break;    }    case "EXTRA":    {    string define = make_unique_name("extra",base,"defined");    addfuncs += IFDEF(define, x[e+1]);    ret += DEFINE(define);    e++;    break;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1840:    string lname = mkname(base, name);    mapping attributes=parse_attributes(proto[1..]);       ParseBlock subclass = ParseBlock(body[1..sizeof(body)-2],    mkname(base, name), name);    string program_var = mkname(base, name, "program");       string define = make_unique_name("class", base, name, "defined");       ret+=DEFINE(define); -  ret+=({sprintf("DEFAULT_CMOD_STORAGE struct program *%s=NULL;\n" -  "static int %s_fun_num=-1;\n", -  program_var, program_var)}); +  global_declarations += +  ({sprintf("DEFAULT_CMOD_STORAGE struct program *%s=NULL;\n", +  program_var)}); +  global_declarations += +  IFDEF(program_var+"_fun_num_used", +  ({sprintf("DEFAULT_CMOD_STORAGE int %s_fun_num=-1;", +  program_var)}));    ret+=subclass->declarations;    ret+=subclass->code; -  +  // Restore THIS to the parent class. +  ret+= +  IFDEF("THIS_" + upper_case(base), +  DEFINE("THIS", "THIS_" + upper_case(base)));    -  +  need_obj_defines["tObjImpl_"+upper_case(lname)] = 1; +  map_types[subclass->local_id] = ({ define, "return "+program_var+"->id;" }); +  +  check_used[program_var+"_fun_num"]=1;    addfuncs+=    IFDEF(define,    ({    IFDEF("PROG_"+upper_case(lname)+"_ID",    ({    PC.Token(sprintf(" START_NEW_PROGRAM_ID(%s);\n",    upper_case(lname)),    proto[0]->line),    "#else\n",    PC.Token(" start_new_program();\n",    proto[0]->line),    })), -  +  PC.Token(sprintf(" %s = Pike_compiler->new_program;\n", +  program_var), +  proto[0]->line),    IFDEF("tObjImpl_"+upper_case(lname),    0, -  DEFINE("tObjImpl_"+upper_case(lname), "tObj")), +  DEFINE("tObjIs_"+upper_case(lname), +  sprintf("%O", sprintf("\3\1\x7f%3c", +  subclass->local_id)))+ +  DEFINE("tObjImpl_"+upper_case(lname), +  sprintf("%O", sprintf("\3\0\x7f%3c", +  subclass->local_id)))),    })+    subclass->addfuncs+    ({    attributes->program_flags?    PC.Token(sprintf(" Pike_compiler->new_program->flags |= %s;\n",    attributes->program_flags),    proto[1]->line):"",    PC.Token(sprintf(" %s=end_program();\n",program_var),    proto[0]->line), -  PC.Token(sprintf(" %s_fun_num=add_program_constant(%O,%s,%s);\n", +  PC.Token(sprintf("#ifdef %[0]s_fun_num_used\n%s_fun_num=\n#endif\n" +  +" add_program_constant(%O,%s,%s);\n",    program_var,    name,    program_var,    attributes->flags || "0"),    proto[0]->line),    })    );    exitfuncs+=    IFDEF(define,    subclass->exitfuncs+
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:1900:    break;    }       case "PIKEVAR":    {    int pos = search(x, PC.Token(";",0), e);    int pos2 = parse_type(x, e+1);    mixed name = x[pos2];    PikeType type = PikeType(x[e+1..pos2-1]);    string define = make_unique_name("var",name,base,"defined"); +  while( x[pos2+1] == "." ) +  { +  name = (string)name + (string)x[pos2+1]+ (string)x[pos2+2]; +  pos2+=2; +  }    mapping attributes = parse_attributes(x[pos2+1..pos]); -  +    // werror("type: %O\n",type); -  +  mixed csym = attributes->c_name || name; +  if( !has_value( csym, "." ) ) +  {    thestruct+=    IFDEF(define, -  ({ sprintf(" %s %s;\n",type->c_storage_type(1),name) })); +  ({ PC.Token(sprintf(" %s %s;\n", +  type->c_storage_type(1), csym), +  x[pos2]->line), +  })); +  } +  else +  { +  if( name[0] == "." ) +  name = name[1..]; +  } +     addfuncs+=    IFDEF(define,    ({ -  sprintf(" PIKE_MAP_VARIABLE(%O, %s_storage_offset + OFFSETOF(%s_struct, %s),\n" +  PC.Token(sprintf(" PIKE_MAP_VARIABLE(%O, %s_storage_offset + OFFSETOF(%s_struct, %s),\n"    " %s, %s, %s);", -  (string)name, base, base, name, +  ((string)name/".")[-1], base, base, csym,    type->output_c_type(), type->type_number(),    attributes->flags || "0"), -  +  x[pos2]->line),    }));    ret+=DEFINE(define);    ret+=({ PC.Token("DECLARE_STORAGE") });    e = pos;    break;    }       case "CVAR":    {    int pos = search(x,PC.Token(";",0),e);
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2038:    ({ PC.Token(sprintf(" pike_set_prog_optimize_callback(%s);\n",    mkname("optimize",base,"struct"))) }));    }       if(sizeof(thestruct))    {    /* We insert the struct definition after the last    * variable definition    */    string structname = base+"_struct"; -  string this=sprintf("((struct %s *)(Pike_interpreter.frame_pointer->current_storage))",structname); +  string this = sprintf("((struct %s *)(Pike_interpreter.frame_pointer->current_storage + %s_storage_offset))", structname, base);       /* FIXME:    * Add runtime debug to these defines...    * Add defines for parents when possible    */    declarations=    DEFINE("THIS",this)+ // FIXME: we should 'pop' this define later    DEFINE("THIS_"+upper_case(base),this)+    DEFINE("OBJ2_"+upper_case(base)+"(o)",    sprintf("((struct %s *)(o->storage+%s_storage_offset))",
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2100:    break;       array proto=func[..p-1];    p=parse_type(proto,0);    if(arrayp(proto[p]))    {    error("%s:%d: Missing return type?\n",    proto[p][0]->file||"-",    proto[p][0]->line);    } -  string name=(string)proto[p]; +  string name=""; +  do { +  name += (string)proto[p]; +  p++; +  } while(!arrayp(proto[p]));    name_occurances[name]++;    }       for(int f=1;f<sizeof(x);f++)    {    array func=x[f];    int p;    for(p=0;p<sizeof(func);p++)    if(arrayp(func[p]) && func[p][0]=="{")    break;    -  +  if (p >= sizeof(func)) { +  error("%s:%d: Invalid function declaration.\n", +  func[0]->file||"-", +  func[0]->line); +  } +     array proto=func[..p-1];    array body=func[p];    array rest=func[p+1..];       // Not all versions of Pike allow Token objects    // to be indexed.    catch {    foreach(Array.flatten(proto), string t)    if(has_prefix((string)t, "/*!"))    body = ({t})+body;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2174:      // werror("name=%s\n",name);   // werror(" rettype=%O\n",rettype);   // werror(" args=%O\n",args);       ret+=({    sprintf("#define %s\n", define),    });       if (!attributes->efun) { -  ret += ({ -  sprintf("DEFAULT_CMOD_STORAGE ptrdiff_t %s = 0;\n", func_num), +  check_used[func_num] = 1; +  global_declarations += ({ +  IFDEF(func_num+"_used", +  ({ sprintf("DEFAULT_CMOD_STORAGE ptrdiff_t %s = -1;\n", +  func_num) }), +  0)    });    }       // werror("%O %O\n",proto,args);    int last_argument_repeats, ignore_more_args;    if (sizeof(args_tmp)) {    array last_arg = args_tmp[-1];    if (sizeof (last_arg) > 1) {    if (!arrayp(last_arg[-2]) && "..." == (string)last_arg[-2]) {    last_argument_repeats = 1;    args_tmp[-1] = last_arg[..sizeof(last_arg)-3] + ({last_arg[-1]});    }    } -  else +  else if( sizeof(last_arg)) +  {    if (!arrayp(last_arg[0]) && "..." == (string)last_arg[0]) {    ignore_more_args = 1;    args_tmp = args_tmp[..sizeof (args_tmp) - 2];    }    } -  +  else +  { +  warn("%s:%s Failed to parse types\n", location,name); +  } +  }    array(Argument) args=map(args_tmp,Argument);    // werror("%O %O\n",proto,args);    // werror("parsed args: %O\n", args);       if((<"`<", "`>", "`==", "_equal">)[name])    {    if(sizeof(args) != 1)    {    warn("%s must take one argument.\n");    }
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2248:    }    }      // werror("NAME: %O\n",name);   // werror("type: %O\n", type);   // werror("C type: %O\n", type->output_c_type());       if (attributes->prototype) {    funcname = "NULL";    } else { +  if (attributes->export) {    ret+=({ -  +  sprintf("PMOD_EXPORT void %s(INT32 args) ",funcname), +  }); +  } else { +  ret+=({    sprintf("DEFAULT_CMOD_STORAGE void %s(INT32 args) ",funcname), -  +  }); +  } +  ret += ({    "{","\n",    });       int min_args=sizeof(args);    int max_args=sizeof(args);    int repeat_arg = -1;       if(last_argument_repeats)    {    min_args--;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2271:    repeat_arg = min_args;    args[-1]->_c_type = "struct svalue *";    }    else if (ignore_more_args)    max_args = 0x7fffffff;       while(min_args>0 && args[min_args-1]->may_be_void())    min_args--;       foreach(args, Argument arg) +  if( arg->name() != "UNUSED" ) {    ret+=({    PC.Token(sprintf("%s %s;\n",arg->c_type(), arg->name()),    arg->line()),    }); -  +  if (arg->c_type() == "struct object *") { +  ret += ({ +  PC.Token(sprintf("int %s_inh_num;\n", arg->name()), +  arg->line()), +  }); +  } +  }          int argnum;       argnum=0;    string argbase;    string num_arguments;    if(min_args == max_args)    {    ret+=({
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2322:    max_args), proto[0]->line)    });    }    }       string check_argbase = argbase;       foreach(args, Argument arg)    {    int got_void_or_zero_check = 0; -  +  if( arg->name() == "UNUSED" ) +  { +  // simply skip directly for now. +  // should probably also handle ... etc? +  argnum++; +  continue; +  }    if (argnum == repeat_arg) {    // Begin the argcnt loop.    check_argbase = "+argcnt"+argbase;    ret += ({ PC.Token(sprintf("if (args > %d) {\n"    " INT32 argcnt = 0;\n"    " do {\n"    " dmalloc_touch_svalue(Pike_sp%+d%s);\n",    argnum, argnum, check_argbase),    arg->line()) });    }       else {    int void_or_zero = arg->may_be_void_or_zero (2, 1);    if (void_or_zero == 2) {    if (!(<"int","mixed">)[arg->basetype()]) {    ret+=({ -  PC.Token(sprintf("if (args > %d &&" -  " (TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT ||" +  PC.Token(sprintf("if (args > %d &&\n" +  " (TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT ||\n"    " Pike_sp[%d%s].u.integer)) {\n",    argnum,    argnum, check_argbase,    argnum, check_argbase), arg->line()),    });    } else {    ret+=({ -  PC.Token(sprintf("if (args > %d) {\n",argnum), arg->line()), +  PC.Token(sprintf("if ((args > %d) &&\n" +  " ((TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT) ||\n" +  " (SUBTYPEOF(Pike_sp[%d%s]) != NUMBER_UNDEFINED))) {\n", +  argnum, +  argnum, check_argbase, +  argnum, check_argbase), arg->line()),    });    }    got_void_or_zero_check = 1;    }       else if (void_or_zero == 1) {    if (!(<"int", "mixed">)[arg->basetype()]) {    ret += ({ -  PC.Token (sprintf ("if (TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT ||" +  PC.Token (sprintf ("if (TYPEOF(Pike_sp[%d%s]) != PIKE_T_INT ||\n"    " Pike_sp[%d%s].u.integer) {\n",    argnum, check_argbase,    argnum, check_argbase), arg->line()),    });    got_void_or_zero_check = 1;    }    }    }       check_arg: {    if(arg->is_c_type() && arg->basetype() == "string")    { -  +  // FIXME: Probably dead code!    /* Special case for 'char *' */    /* This will have to be amended when we want to support    * wide strings    */    ret+=({ -  PC.Token(sprintf("if(TYPEOF(Pike_sp[%d%s]) != PIKE_T_STRING || Pike_sp[%d%s].u.string->shift_size)", +  PC.Token(sprintf("if(TYPEOF(Pike_sp[%d%s]) != PIKE_T_STRING ||\n" +  " Pike_sp[%d%s].u.string->shift_size)",    argnum,check_argbase,    argnum,check_argbase), arg->line())    });    } else {       switch(arg->realtype())    { -  +  case "string": +  // Clamp the integer range to 32 bit signed. +  [int low, int high] = clamp_int_range(arg->type(), "string"); +  if ((low >= 0) && (high <= 0xffff)) { +  // Narrow string. +  if (high <= 0xff) { +  if (low > 0) { +  ret += ({ +  PC.Token(sprintf("if((TYPEOF(Pike_sp[%d%s]) != PIKE_T_%s) || " +  "Pike_sp[%d%s].u.string->size_shift || " +  "string_has_null(Pike_sp[%d%s].u.string))", +  argnum, check_argbase, +  upper_case(arg->basetype()), +  argnum, check_argbase, +  argnum, check_argbase), +  arg->line()), +  }); +  } else { +  ret += ({ +  PC.Token(sprintf("if((TYPEOF(Pike_sp[%d%s]) != PIKE_T_%s) || " +  "Pike_sp[%d%s].u.string->size_shift)", +  argnum, check_argbase, +  upper_case(arg->basetype()), +  argnum, check_argbase), +  arg->line()), +  }); +  } +  } else { +  ret += ({ +  PC.Token(sprintf("if((TYPEOF(Pike_sp[%d%s]) != PIKE_T_%s) || " +  "(Pike_sp[%d%s].u.string->size_shift > 1))", +  argnum, check_argbase, +  upper_case(arg->basetype()), +  argnum, check_argbase), +  arg->line()), +  }); +  } +  break; +  } +  // FALL_THROUGH    default:    ret+=({    PC.Token(sprintf("if(TYPEOF(Pike_sp[%d%s]) != PIKE_T_%s)",    argnum,check_argbase,    upper_case(arg->basetype())),arg->line())    });    break;       case "program":    ret+=({
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2438:    argnum+1,    (argnum == repeat_arg)?"+argcnt":"",    arg->typename()),arg->line()),    });    }       if (argnum == repeat_arg) {    // End the argcnt loop.    ret += ({ PC.Token(sprintf (" } while (++argcnt < %s-%d);\n"    " %s=Pike_sp%+d%s;\n" -  "} else %s=0;\n", +  "} else %s = NULL;\n",    num_arguments, argnum,    arg->name(), argnum, argbase,    arg->name()),    arg->line()) });    }       else {    switch(arg->c_type())    {    case "INT_TYPE":
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2524:    argnum,argbase),arg->line())    });       }else{    ret+=({    PC.Token(sprintf("debug_malloc_pass(%s=Pike_sp[%d%s].u.%s);\n",    arg->name(),    argnum,argbase,    arg->basetype()),arg->line())    }); +  if (arg->c_type() == "struct object *") { +  ret += ({ +  PC.Token(sprintf("%s_inh_num = SUBTYPEOF(Pike_sp[%d%s]);\n", +  arg->name(), +  argnum,argbase),arg->line()) +  });    } -  +  }       case "program":    }       if (got_void_or_zero_check)    {    string zero_val;    switch (arg->c_type()) {    case "INT_TYPE": zero_val = "0"; break;    case "FLOAT_TYPE": zero_val = "0.0"; break;
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2590:    type=PikeType(PC.Token("|"), tmp->type);    attributes=`|(@ tmp->attributes);       array out=generate_overload_func_for(tmp,    2,    0,    0x7fffffff,    common_name,    attributes);    -  +     /* FIXME: This definition should be added    * somewhere outside of all #ifdefs really!    * -Hubbe    */ -  +  global_declarations += ({ +  IFDEF(func_num+"_used", +  ({sprintf("DEFAULT_CMOD_STORAGE ptrdiff_t %s = -1;\n", func_num)})), +  }); +  check_used[func_num] = 1;    ret+=IFDEF(tmp->define, ({    sprintf("#define %s\n",define), -  sprintf("DEFAULT_CMOD_STORAGE ptrdiff_t %s = 0;\n", func_num), +     sprintf("DEFAULT_CMOD_STORAGE void %s(INT32 args) ",funcname),    "{\n",    })+out+({    "}\n",    })); -  +     }    }    ret+=rest;    -  +     if (attributes->efun) {    if(attributes->optfunc)    addfuncs+=IFDEF(define,({    PC.Token(sprintf(" ADD_EFUN2(%O, %s, %s, %s, %s, 0);\n",    attributes->name || name,    funcname,    type->output_c_type(),    (attributes->optflags)|| "0",    attributes->optfunc    ), proto[0]->line),
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2630:    else    addfuncs+=IFDEF(define,({    PC.Token(sprintf(" ADD_EFUN(%O, %s, %s, %s);\n",    attributes->name || name,    funcname,    type->output_c_type(),    (attributes->optflags)|| "0"    ), proto[0]->line),    }));    } else { +  check_used[func_num] = 1;    addfuncs+=IFDEF(define, ({ -  PC.Token(sprintf(" %s =\n", func_num)), +  IFDEF(func_num+"_used", +  ({PC.Token(sprintf(" %s =", func_num))})),    PC.Token(sprintf(" ADD_FUNCTION2(%O, %s, %s, %s, %s);\n",    attributes->name || name,    funcname,    type->output_c_type(),    attributes->flags || "0" ,    attributes->optflags ||    "OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT"    ),proto[0]->line),    }));    }
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2697:    while ((i = search(tokens, PC.Token("MK_STRING_SVALUE"), i+1)) != -1) {    // werror("MK_STRING_SVALUE found: %O\n", tokens[i..i+10]);    if (arrayp(tokens[i+1]) && (sizeof(tokens[i+1]) == 3)) {    tokens[i] = PC.Token(allocate_string_svalue((string)tokens[i+1][1]));    tokens = tokens[..i] + tokens[i+2..];    }    }    return tokens;   }    + class ArgCheckFunction(array tokens) + { + } +    class Handler {    inherit "/master";       mixed resolv(string identifier, string|void current_file,    object|void current_handler) {    return predef::master()->resolv(identifier, current_file,    current_handler);    }       void create(mapping|void predefines) {    ::create();    if (predefines) this_program::predefines = predefines;    }   }    -  + int find_identifier( array in, string ident ) + { +  foreach( in, mixed q ) +  { +  if( objectp(q) ) +  { +  if( q == ident ) +  return 1; +  } +  else if( arrayp( q ) ) +  { +  if( find_identifier( q, ident ) ) +  return 1; +  } +  } + } +  + array resolve_obj_defines() + { +  array res = ({}); +  +  foreach( need_obj_defines; string key; int|string id ) +  { +  if( intp( id ) ) +  { +  m_delete( need_obj_defines, key ); +  continue; /* type in this file. Not external. */ +  } +  } +  if( sizeof( need_obj_defines ) ) +  { +  res += ({ "{ int i=0;\n"}); +  foreach( sort(indices(need_obj_defines)), string key ) +  { +  string id = need_obj_defines[key]; +  int local_id = ++gid; +  res += ({ +  sprintf("#ifndef %s\n" +  "# define %[0]s %s\n" +  "{\n" +  " struct program *tmp = resolve_program(%s);\n" +  " if( tmp ) {\n" +  " ___cmod_ext_used[i].from = %d;\n" +  " ___cmod_ext_used[i].to = tmp->id;\n" +  " i++;\n" +  " }\n" +  "}\n" +  "#endif /* %[0]s */\n", +  key, sprintf("%O", sprintf("\3\0\x7f%3c", local_id)), +  allocate_string(sprintf("%O",id)), local_id) +  }); +  } +  res += ({"}\n"}); +  } +  return res; + } +    int main(int argc, array(string) argv)   {    mixed x;    -  +  string base = ""; +     warnings = 1;    api = (int)precompile_api_version;       string outpath;    if( has_suffix( lower_case(dirname( argv[0] )), "standalone.pmod" ) )    usage = "pike -x " + basename( argv[0] )-".pike" + " " + usage;    foreach(Getopt.find_all_options( argv, ({    ({ "api", Getopt.HAS_ARG, "--api"/"," }),    ({ "help", Getopt.NO_ARG, "-h,--help"/"," }),    ({ "output", Getopt.HAS_ARG, "-o,--out"/"," }),    ({ "version", Getopt.NO_ARG, "-v,--version"/"," }),    ({ "warnings", Getopt.NO_ARG, "-w,--warnings"/"," }), -  +  ({ "base", Getopt.HAS_ARG, "-b,--base"/"," }),    })), array opt ) {    switch(opt[0]) {    case "version":    write( "Precompile format version "+precompile_api_version+"\n");    return 0;    case "help":    write( usage );    return 0;       case "api":
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2789: Inside #if 0
   // The --api option was not supported by the API level 2 precompiler.    werror("API level 2 and earlier are implicit, and\n"    "must not be specified with the --api option.\n");    return 1;    }   #endif    break;    case "output":    outpath = opt[1];    break; +  case "base": +  base = opt[1]; +  break;    }    }    argv = Getopt.get_args(argv);    if( sizeof( argv ) < 2 )    {    write((usage/"\n")[0]+"\n");    return 1;    }    string file = argv[1];   
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2839: Inside #if constant(Pike.__HAVE_CPP_PREFIX_SUPPORT__)
   "#define %<s %s", x, y);    },    "cmod_CONCAT()" :    lambda(string ... s) { return s*""; },    "cmod___CMOD__" : "1",    ]))    ]));    } else   #endif    if (has_value(x, "cmod_include") || has_value(x, "cmod_define") ){ -  werror("%[0]s:1: Warning: It looks like %[0]O might features not present in\n" +  werror("%[0]s:1: Warning: It looks like %[0]O might use features not present in\n"    "%[0]s:1: Warning: the pike used to run the precompiler\n", file);    }    x=split(x);    x=PC.tokenize(x,file);    x = convert_comments(x);    x=PC.hide_whitespaces(x);    x=PC.group(x);       x = ({ -  sprintf("/* Generated from %O by precompile.pike\n" +  sprintf("/* Generated from %O by precompile.pike running %s\n"    " *\n"    " * Do NOT edit this file.\n"    " */\n", -  argv[1]), +  argv[1], version()),    }) + DEFINE("PRECOMPILE_API_VERSION", (string)precompile_api_version) + ({    "\n\n",    })   #if constant(Pike.__HAVE_CPP_PREFIX_SUPPORT__)    + DEFINE("cmod___CMOD__", "1")   #endif    + x;      // werror("%O\n",x);       x = recursive(allocate_strings, x);    -  ParseBlock tmp=ParseBlock(x,"",""); +  ParseBlock tmp=ParseBlock(x, base, "");       tmp->declarations += ({    "\n\n" -  +  "#ifndef PIKE_UNUSED_ATTRIBUTE\n" +  "#define PIKE_UNUSED_ATTRIBUTE\n" +  "#endif\n" +  "#define CMOD_MAP_PROGRAM_IDS_DEFINED 1\n" +  "static int ___cmod_map_program_ids(int id) PIKE_UNUSED_ATTRIBUTE;\n"    "#ifndef TYPEOF\n"    "/* Compat with older Pikes. */\n"    "#define TYPEOF(SVAL)\t((SVAL).type)\n"    "#define SUBTYPEOF(SVAL)\t((SVAL).subtype)\n"    "#define SET_SVAL_TYPE(SVAL, TYPE)\t(TYPEOF(SVAL) = TYPE)\n"    "#define SET_SVAL_SUBTYPE(SVAL, TYPE)\t(SUBTYPEOF(SVAL) = TYPE)\n"    "#define SET_SVAL(SVAL, TYPE, SUBTYPE, FIELD, EXPR) do {\t\\\n"    " /* Set the type afterwards to avoid a clobbered\t\\\n"    " * svalue in case EXPR throws. */\t\t\t\\\n"    " (SVAL).u.FIELD = (EXPR);\t\t\t\t\\\n"    " SET_SVAL_TYPE((SVAL), (TYPE));\t\t\t\\\n"    " SET_SVAL_SUBTYPE((SVAL), (SUBTYPE));\t\t\\\n"    " } while(0)\n"    "#endif /* !TYPEOF */\n" -  +  "#ifndef PIKE_UNUSED\n" +  "/* Compat with Pike 7.8 and earlier. */\n" +  "/* NB: Not strictly correct; PIKE_UNUSED was added the\n" +  " * day after set_program_id_to_id(), but good enough.\n" +  " */\n" +  "#ifndef UNUSED\n" +  "#define UNUSED(X) X\n" +  "#endif\n" +  "#ifndef set_program_id_to_id\n" +  "/* NB: Recent Pike 7.8 has a #define that conflicts with\n" +  " * the following declaration.\n" +  " */\n" +  "static void set_program_id_to_id(void*UNUSED(id)){}\n" +  "#endif\n" +  "#else /* */\n" +  "PMOD_EXPORT void set_program_id_to_id( int (*to)(int) );\n" +  "#endif /* !PIKE_UNUSED */\n" +  "#if !defined(string_has_null) && !defined(STRING_CONTENT_CHECKED)\n" +  "/* This symbol was added as a macro in Pike 7.7.20, and is an\n" +  " * inline function in Pike 7.9.4 and later, at which time the\n" +  " * flag STRING_CONTENT_CHECKED was added.\n" +  " */\n" +  "#define string_has_null(X) (strlen((X)->str)!=(size_t)(X)->len)\n" +  "#endif\n"    "\n\n", -  // FIXME: Ought to default to static in 7.9. +     "#ifndef DEFAULT_CMOD_STORAGE\n" -  "#define DEFAULT_CMOD_STORAGE\n" +  "#define CMOD_COND_USED\n" +  "#define DEFAULT_CMOD_STORAGE static\n"    "#endif\n"    });    -  +  +  tmp->addfuncs = +  IFDEF("CMOD_MAP_PROGRAM_IDS_DEFINED", +  resolve_obj_defines() + +  ({ "set_program_id_to_id( ___cmod_map_program_ids );\n" })) +  + tmp->addfuncs +  + IFDEF("CMOD_MAP_PROGRAM_IDS_DEFINED", +  ({ "set_program_id_to_id( 0 );" })); +     if (last_str_id) {    // Add code for allocation and deallocation of the strings.    tmp->addfuncs =    ({ "\n#ifdef module_strings_declared\n" }) +    stradd +    ({ "#endif\n" }) + tmp->addfuncs;    tmp->exitfuncs += ({    sprintf("\n#ifdef module_strings_declared\n"    "{\n"    " int i;\n"    " for(i=0; i < %d; i++) {\n"    " if (module_strings[i]) free_string(module_strings[i]);\n"    " module_strings[i] = NULL;\n"    " }\n"    "}\n"    "#endif\n",    last_str_id),    }); -  +     tmp->declarations += ({    sprintf("#define module_strings_declared\n"    "static struct pike_string *module_strings[%d] = {\n"    "%s};\n",    last_str_id, " NULL,\n"*last_str_id),    });       // Same for svalues.    // NOTE: This code needs changing in several aspects if    // support for other svalues than strings is added.
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2934:    last_svalue_id),    });    tmp->declarations += ({    sprintf("#define module_svalues_declared\n"    "static struct svalue module_svalues[%d];\n",    last_svalue_id),    });    }    }    -  x=tmp->code; +  x = tmp->code; +  +  x += ({ +  "\n" +  "#ifdef CMOD_MAP_PROGRAM_IDS_DEFINED\n" +  "static int ___cmod_map_program_ids(int id)\n" +  "{\n" +  " if( (id&0x7f000000) != 0x7f000000 ) return id;\n" +  " id = id&0x00ffffff;\n" +  }); +  +  if( sizeof(map_types) ) +  { +  x += ({ " switch(id) {\n" }); +  foreach( sort(indices(map_types)), int i ) +  { +  string how = map_types[i]; +  if( how[0] ) +  x += ({ "#ifdef "+how[0]+"\n" }); +  x += ({ " case "+i+":\n "+how[1]+"\n break;\n" }); +  if( how[0] ) +  x += ({ "#endif\n" }); +  } +  x += ({ " };\n\n" }); +  } +  +  if( sizeof( need_obj_defines ) ) +  { +  tmp->declarations += ({ +  "static struct { INT32 from;INT32 to; } ___cmod_ext_used[" + +  sizeof( need_obj_defines ) + "];\n" +  }); +  +  x += ({ +  " {\n" +  " int i = 0;\n" +  " while(___cmod_ext_used[i].from ) {\n" +  " if( ___cmod_ext_used[i].from == id ) {\n" +  " return ___cmod_ext_used[i].to;\n" +  " }\n" +  " i++;\n" +  " }\n" +  " }\n" +  }); +  } +  x += ({ +  " return 0;\n" +  "}\n" +  "#endif /* CMOD_MAP_PROGRAM_IDS_DEFINED */\n" +  }); +  +  tmp->code = x;    x=recursive(replace,x,PC.Token("INIT",0),tmp->addfuncs);    int need_init;    if ((need_init = equal(x, tmp->code)))    {    // No INIT, add our own stuff..       x+=({    "PIKE_MODULE_INIT {\n",    tmp->addfuncs,    "}\n",
pike.git/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike:2970:    werror("Warning: INIT without EXIT. Added PIKE_MODULE_EXIT.\n");    }    } else if (need_init) {    werror("Warning: EXIT without INIT. Added PIKE_MODULE_INIT.\n");    }    tmp->code = x;       // FIXME: This line is fishy; there is no optfuncs in ParseBlock.    x=recursive(replace,x,PC.Token("OPTIMIZE",0),tmp->optfuncs);    +  array(string) cond_used = ({}); +  foreach( sort(indices(check_used)), string key) +  { +  if( find_identifier( x, key ) ) +  tmp->declarations +=({ "#define "+key+"_used 1\n" }); +  else +  cond_used += ({ key }); +  } +  if (sizeof(cond_used)) { +  tmp->declarations += ({ "#ifndef CMOD_COND_USED\n" }); +  foreach(cond_used, string key) { +  tmp->declarations += ({ "# define "+key+"_used 1\n" }); +  } +  tmp->declarations += ({ "#else /* !CMOD_COND_USED */\n" }); +  foreach(cond_used, string key) { +  tmp->declarations += ({ "# undef "+key+"_used\n" }); +  } +  tmp->declarations += ({ "#endif /* !CMOD_COND_USED */\n" }); +  } +  +  tmp->declarations += global_declarations; +  tmp->code = x;    x=recursive(replace,x,PC.Token("DECLARATIONS",0),tmp->declarations);    -  +     if(equal(x,tmp->code))    {    // No OPTIMIZE / DECLARATIONS    // FIXME: Add our own stuff...    // NOTA BENE: DECLARATIONS are not handled automatically    // on the file level    }    Stdio.File out = Stdio.stdout;    if (outpath) {    out = Stdio.File(outpath, "twc", 0666);    }    if(getenv("PIKE_DEBUG_PRECOMPILER"))    out->write(PC.simple_reconstitute(x));    else    out->write(PC.reconstitute_with_line_numbers(x));   }