added experimental new String tag. this tag will revert array usage to "char" sizing and packed strings
authorDavid Anderson <dvander@alliedmods.net>
Tue Nov 07 09:50:09 2006 +0000 (2006-11-07)
changeset 15100a6126f837c
parent 150 42d85020e6ea
child 152 0a99efef8d99
added experimental new String tag. this tag will revert array usage to "char" sizing and packed strings
sourcepawn/compiler/sc.h
sourcepawn/compiler/sc1.c
sourcepawn/compiler/sc2.c
sourcepawn/compiler/sc3.c
sourcepawn/compiler/sc4.c
     1.1 --- a/sourcepawn/compiler/sc.h	Tue Nov 07 00:53:06 2006 +0000
     1.2 +++ b/sourcepawn/compiler/sc.h	Tue Nov 07 09:50:09 2006 +0000
     1.3 @@ -567,9 +567,13 @@
     1.4  SC_FUNC int check_userop(void (*oper)(void),int tag1,int tag2,int numparam,
     1.5                           value *lval,int *resulttag);
     1.6  SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce);
     1.7 +SC_FUNC int checktag(int tags[],int numtags,int exprtag);
     1.8  SC_FUNC int expression(cell *val,int *tag,symbol **symptr,int chkfuncresult);
     1.9  SC_FUNC int sc_getstateid(constvalue **automaton,constvalue **state);
    1.10  SC_FUNC cell array_totalsize(symbol *sym);
    1.11 +SC_FUNC int matchtag_string(int ident, int tag);
    1.12 +SC_FUNC int checktag_string(value *sym1, value *sym2);
    1.13 +SC_FUNC int checktags_string(int tags[], int numtags, value *sym1);
    1.14  
    1.15  /* function prototypes in SC4.C */
    1.16  SC_FUNC void writeleader(symbol *root);
    1.17 @@ -809,6 +813,7 @@
    1.18  SC_VDECL int pc_optimize;     /* (peephole) optimization level */
    1.19  SC_VDECL int pc_memflags;     /* special flags for the stack/heap usage */
    1.20  SC_VDECL int pc_functag;      /* global function tag */
    1.21 +SC_VDECL int pc_tag_string;   /* global string tag */
    1.22  
    1.23  SC_VDECL constvalue sc_automaton_tab; /* automaton table */
    1.24  SC_VDECL constvalue sc_state_tab;     /* state table */
     2.1 --- a/sourcepawn/compiler/sc1.c	Tue Nov 07 00:53:06 2006 +0000
     2.2 +++ b/sourcepawn/compiler/sc1.c	Tue Nov 07 09:50:09 2006 +0000
     2.3 @@ -71,6 +71,7 @@
     2.4  #define VERSION_INT 0x0302
     2.5  
     2.6  int pc_functag = 0;
     2.7 +int pc_tag_string = 0;
     2.8  
     2.9  static void resetglobals(void);
    2.10  static void initglobals(void);
    2.11 @@ -683,7 +684,7 @@
    2.12    verbosity=1;          /* verbosity level, no copyright banner */
    2.13    sc_debug=sCHKBOUNDS|sSYMBOLIC;   /* sourcemod: full debug stuff */
    2.14    pc_optimize=sOPTIMIZE_DEFAULT;   /* sourcemod: full optimization */
    2.15 -  sc_packstr=FALSE;     /* strings are unpacked by default */
    2.16 +  sc_packstr=TRUE;     /* strings are packed by default */
    2.17    sc_compress=FALSE;	/* always disable compact encoding! */
    2.18    sc_needsemicolon=FALSE;/* semicolon required to terminate expressions? */
    2.19    sc_dataalign=sizeof(cell);
    2.20 @@ -1248,6 +1249,7 @@
    2.21    append_constval(&tagname_tab,"_",0,0);/* "untagged" */
    2.22    append_constval(&tagname_tab,"bool",1,0);
    2.23    pc_functag = pc_addfunctag("Function");
    2.24 +  pc_tag_string = pc_addtag("String");
    2.25  
    2.26    add_constant("true",1,sGLOBAL,1);     /* boolean flags */
    2.27    add_constant("false",0,sGLOBAL,1);
    2.28 @@ -1731,6 +1733,8 @@
    2.29  #endif
    2.30        dim[numdim++]=(int)size;
    2.31      } /* while */
    2.32 +    if (ident == iARRAY && tag == pc_tag_string)
    2.33 +      dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
    2.34      assert(sc_curstates==0);
    2.35      sc_curstates=getstates(name);
    2.36      if (sc_curstates<0) {
    2.37 @@ -1989,6 +1993,9 @@
    2.38          #endif
    2.39          dim[numdim++]=(int)size;
    2.40        } while (matchtoken('['));
    2.41 +      /* Change the last dimension to be based on chars instead if we have a string */
    2.42 +      if (tag == pc_tag_string)
    2.43 +        dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
    2.44      } else if (matchtoken('(')) {
    2.45        int dim_ident;
    2.46        symbol *dim_sym;
    2.47 @@ -2072,10 +2079,11 @@
    2.48          /* simple variable, also supports initialization */
    2.49          int ctag = tag;         /* set to "tag" by default */
    2.50          int explicit_init=FALSE;/* is the variable explicitly initialized? */
    2.51 +        int cident=ident;
    2.52          if (matchtoken('=')) {
    2.53            if (!autozero)
    2.54              error(10);
    2.55 -          doexpr(FALSE,FALSE,FALSE,FALSE,&ctag,NULL,TRUE);
    2.56 +          cident=doexpr(FALSE,FALSE,FALSE,FALSE,&ctag,NULL,TRUE);
    2.57            explicit_init=TRUE;
    2.58          } else {
    2.59            if (autozero)
    2.60 @@ -2094,7 +2102,7 @@
    2.61          assert(staging);        /* end staging phase (optimize expression) */
    2.62          stgout(staging_start);
    2.63          stgset(FALSE);
    2.64 -        if (!matchtag(tag,ctag,TRUE))
    2.65 +        if (!matchtag_string(cident, ctag) && !matchtag(tag,ctag,TRUE))
    2.66            error(213);           /* tag mismatch */
    2.67          /* if the variable was not explicitly initialized, reset the
    2.68           * "uWRITTEN" flag that store() set */
    2.69 @@ -2501,7 +2509,7 @@
    2.70        error(6);         /* must be assigned to an array */
    2.71        litidx=1;         /* reset literal queue */
    2.72      } /* if */
    2.73 -    *tag=0;
    2.74 +    *tag=pc_tag_string;
    2.75    } else if (constexpr(&i,tag,NULL)){
    2.76      litadd(i);          /* store expression result in literal table */
    2.77    } else {
    2.78 @@ -2702,6 +2710,7 @@
    2.79  				}
    2.80  				if (matchtoken('['))
    2.81  				{
    2.82 +					cell size;
    2.83  					if (arg->ident == iREFERENCE)
    2.84  					{
    2.85  						error(67, str);
    2.86 @@ -2709,7 +2718,6 @@
    2.87  					do 
    2.88  					{
    2.89  						constvalue *enumroot;
    2.90 -						cell size;
    2.91  						int ignore_tag;
    2.92  						if (arg->dimcount == sDIMEN_MAX)
    2.93  						{
    2.94 @@ -2720,6 +2728,11 @@
    2.95  						arg->dims[arg->dimcount] = size;
    2.96  						arg->dimcount += 1;
    2.97  					} while (matchtoken('['));
    2.98 +					/* Handle strings */
    2.99 +					if (arg->tagcount == 1 && arg->tags[0] == pc_tag_string)
   2.100 +					{
   2.101 +						arg->dims[arg->dimcount-1] = (size + sizeof(cell)-1) / sizeof(cell);
   2.102 +					}
   2.103  					arg->ident=iREFARRAY;
   2.104  				} else if (arg->ident == 0) {
   2.105  					arg->ident = iVARIABLE;
   2.106 @@ -2850,6 +2863,7 @@
   2.107        constexpr(&size,&fieldtag,NULL);  /* get size */
   2.108        needtoken(']');
   2.109      } /* if */
   2.110 +    /* :TODO: do we need a size modifier here for pc_tag_string? */
   2.111      if (matchtoken('='))
   2.112        constexpr(&value,NULL,NULL);      /* get value */
   2.113      /* add_constant() checks whether a variable (global or local) or
   2.114 @@ -3355,6 +3369,9 @@
   2.115      dim[numdim++]=(int)size;
   2.116    } /* while */
   2.117  
   2.118 +  if (tag == pc_tag_string)
   2.119 +    dim[numdim-1] = (size + sizeof(cell)-1) / sizeof(cell);
   2.120 +
   2.121    tok=lex(&val,&str);
   2.122    fpublic=(tok==tPUBLIC) || (tok==tSYMBOL && str[0]==PUBLIC_CHAR);
   2.123    if (fnative) {
   2.124 @@ -3933,6 +3950,8 @@
   2.125        arg->numdim+=1;
   2.126      } while (matchtoken('['));
   2.127      ident=iREFARRAY;            /* "reference to array" (is a pointer) */
   2.128 +    if (checktag(tags, numtags, pc_tag_string))
   2.129 +      arg->dim[arg->numdim - 1] = (size + sizeof(cell) - 1) / sizeof(cell);
   2.130      if (matchtoken('=')) {
   2.131        lexpush();                /* initials() needs the "=" token again */
   2.132        assert(litidx==0);        /* at the start of a function, this is reset */
   2.133 @@ -5682,7 +5701,7 @@
   2.134      rettype|=uRETVALUE;                 /* function returns a value */
   2.135      /* check tagname with function tagname */
   2.136      assert(curfunc!=NULL);
   2.137 -    if (!matchtag(curfunc->tag,tag,TRUE))
   2.138 +    if (!matchtag_string(ident, tag) && !matchtag(curfunc->tag,tag,TRUE))
   2.139        error(213);                       /* tagname mismatch */
   2.140      if (ident==iARRAY || ident==iREFARRAY) {
   2.141        int dim[sDIMEN_MAX],numdim;
     3.1 --- a/sourcepawn/compiler/sc2.c	Tue Nov 07 00:53:06 2006 +0000
     3.2 +++ b/sourcepawn/compiler/sc2.c	Tue Nov 07 09:50:09 2006 +0000
     3.3 @@ -1795,7 +1795,7 @@
     3.4    int i;
     3.5    ucell val,c;
     3.6  
     3.7 -  i=sizeof(ucell)-(sCHARBITS/8); /* start at most significant byte */
     3.8 +  i=0; /* start at least significant byte */
     3.9    val=0;
    3.10    while (*lptr!='\"' && *lptr!='\0') {
    3.11      if (*lptr=='\a') {          /* ignore '\a' (which was inserted at a line concatenation) */
    3.12 @@ -1806,14 +1806,16 @@
    3.13      if (c>=(ucell)(1 << sCHARBITS))
    3.14        error(43);                /* character constant exceeds range */
    3.15      val |= (c << 8*i);
    3.16 -    if (i==0) {
    3.17 +    if (i==sizeof(ucell)-(sCHARBITS/8)) {
    3.18        litadd(val);
    3.19        val=0;
    3.20 -    } /* if */
    3.21 -    i=(i+sizeof(ucell)-(sCHARBITS/8)) % sizeof(ucell);
    3.22 +      i=0;
    3.23 +    } else {
    3.24 +      i=i+1;
    3.25 +    }
    3.26    } /* if */
    3.27    /* save last code; make sure there is at least one terminating zero character */
    3.28 -  if (i!=(int)(sizeof(ucell)-(sCHARBITS/8)))
    3.29 +  if (i!=0)
    3.30      litadd(val);        /* at least one zero character in "val" */
    3.31    else
    3.32      litadd(0);          /* add full cell of zeros */
    3.33 @@ -1875,7 +1877,7 @@
    3.34           "*=", "/=", "%=", "+=", "-=", "<<=", ">>>=", ">>=", "&=", "^=", "|=",
    3.35           "||", "&&", "==", "!=", "<=", ">=", "<<", ">>>", ">>", "++", "--",
    3.36           "...", "..", "::",
    3.37 -         "assert", "*begin", "break", "case", "char", "const", "continue", "default",
    3.38 +         "assert", "*begin", "break", "case", "chars", "const", "continue", "default",
    3.39           "defined", "do", "else", "*end", "enum", "exit", "for", "forward", "funcenum", "goto",
    3.40           "if", "native", "new", "decl", "operator", "public", "return", "sizeof",
    3.41           "sleep", "state", "static", "stock", "switch", "tagof", "*then", "while",
    3.42 @@ -2008,6 +2010,7 @@
    3.43      lptr+=1;            /* skip double quote */
    3.44      if ((stringflags & RAWMODE)!=0)
    3.45        lptr+=1;          /* skip "escape" character too */
    3.46 +    /* Note that this should always be packedstring() for SourcePawn */
    3.47      lptr=sc_packstr ? packedstring(lptr,stringflags) : unpackedstring(lptr,stringflags);
    3.48      if (*lptr=='\"')
    3.49        lptr+=1;          /* skip final quote */
     4.1 --- a/sourcepawn/compiler/sc3.c	Tue Nov 07 00:53:06 2006 +0000
     4.2 +++ b/sourcepawn/compiler/sc3.c	Tue Nov 07 09:50:09 2006 +0000
     4.3 @@ -282,6 +282,44 @@
     4.4    return TRUE;
     4.5  }
     4.6  
     4.7 +SC_FUNC int checktags_string(int tags[], int numtags, value *sym1)
     4.8 +{
     4.9 +  int i;
    4.10 +  if (sym1->ident == iARRAY || sym1->ident == iREFARRAY)
    4.11 +  {
    4.12 +    return FALSE;
    4.13 +  }
    4.14 +  for (i=0; i<numtags; i++) {
    4.15 +    if ((sym1->tag == pc_tag_string && tags[i] == 0) ||
    4.16 +		(sym1->tag == 0 && tags[i] == pc_tag_string))
    4.17 +      return TRUE;
    4.18 +  }
    4.19 +  return FALSE;
    4.20 +}
    4.21 +
    4.22 +SC_FUNC int checktag_string(value *sym1, value *sym2)
    4.23 +{
    4.24 +  if (sym1->ident == iARRAY || sym2->ident == iARRAY
    4.25 +	  || sym1->ident == iREFARRAY || sym2->ident == iREFARRAY)
    4.26 +  {
    4.27 +    return FALSE;
    4.28 +  }
    4.29 +  if ((sym1->tag == pc_tag_string && sym2->tag == 0)
    4.30 +	  || (sym1->tag == 0 && sym2->tag == pc_tag_string))
    4.31 +  {
    4.32 +    return TRUE;
    4.33 +  }
    4.34 +
    4.35 +  return FALSE;
    4.36 +}
    4.37 +
    4.38 +SC_FUNC int matchtag_string(int ident, int tag)
    4.39 +{
    4.40 +  if (ident == iARRAY || ident == iREFARRAY)
    4.41 +    return FALSE;
    4.42 +  return (tag == pc_tag_string) ? TRUE : FALSE;
    4.43 +}
    4.44 +
    4.45  SC_FUNC int matchtag(int formaltag,int actualtag,int allowcoerce)
    4.46  {
    4.47    if (formaltag!=actualtag) {
    4.48 @@ -781,7 +819,7 @@
    4.49          error(213);             /* tagname mismatch */
    4.50        lval1->constval=calc(lval1->constval,oper,lval2->constval,&lval1->boolresult);
    4.51      } else {
    4.52 -      if (!matchtag(lval1->tag,lval2->tag,FALSE))
    4.53 +      if (!checktag_string(lval1, lval2) && !matchtag(lval1->tag,lval2->tag,FALSE))
    4.54          error(213);             /* tagname mismatch */
    4.55        (*oper)();                /* do the (signed) operation */
    4.56        lval1->ident=iEXPRESSION;
    4.57 @@ -1205,7 +1243,7 @@
    4.58      check_userop(NULL,lval2.tag,lval3.tag,2,&lval3,&lval2.tag);
    4.59      store(&lval3);      /* now, store the expression result */
    4.60    } /* if */
    4.61 -  if (!oper && !matchtag(lval3.tag,lval2.tag,TRUE))
    4.62 +  if (!oper && !checktag_string(&lval3, &lval2) && !matchtag(lval3.tag,lval2.tag,TRUE))
    4.63      error(213);         /* tagname mismatch (if "oper", warning already given in plunge2()) */
    4.64    if (lval3.sym)
    4.65      markusage(lval3.sym,uWRITTEN);
    4.66 @@ -1658,6 +1696,10 @@
    4.67            popreg(sPRI);         /* restore PRI (result of rvalue()) */
    4.68          sideeffect=TRUE;
    4.69          return FALSE;
    4.70 +/* This is temporarily disabled because we detect it automatically.
    4.71 + * Thus, it could be weird if both were used at once
    4.72 + */
    4.73 +#if 0
    4.74        case tCHAR:               /* char (compute required # of cells */
    4.75          if (lval->ident==iCONSTEXPR) {
    4.76            lval->constval *= sCHARBITS/8;  /* from char to bytes */
    4.77 @@ -1670,6 +1712,7 @@
    4.78            addr2cell();          /* truncate to number of cells */
    4.79          } /* if */
    4.80          return FALSE;
    4.81 +#endif
    4.82        default:
    4.83          lexpush();
    4.84          return lvalue;
    4.85 @@ -1745,7 +1788,7 @@
    4.86            assert(sym->dim.array.level>=0 && sym->dim.array.level<sDIMEN_MAX);
    4.87            lval1->arrayidx[sym->dim.array.level]=lval2.constval;
    4.88          } /* if */
    4.89 -        if (close==']') {
    4.90 +        if (close==']' && !(sym->tag == pc_tag_string && sym->dim.array.level == 0)) {
    4.91            /* normal array index */
    4.92            if (lval2.constval<0 || sym->dim.array.length!=0 && sym->dim.array.length<=lval2.constval)
    4.93              error(32,sym->name);        /* array index out of bounds */
    4.94 @@ -1826,7 +1869,11 @@
    4.95        } /* if */
    4.96        assert(sym->dim.array.level==0);
    4.97        /* set type to fetch... INDIRECTLY */
    4.98 -      lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
    4.99 +      if (sym->tag == pc_tag_string) {
   4.100 +        lval1->ident = iARRAYCHAR;
   4.101 +      } else {
   4.102 +        lval1->ident= (char)((close==']') ? iARRAYCELL : iARRAYCHAR);
   4.103 +      }
   4.104        /* if the array index is a field from an enumeration, get the tag name
   4.105         * from the field and save the size of the field too. Otherwise, the
   4.106         * tag is the one from the array symbol.
   4.107 @@ -2105,7 +2152,7 @@
   4.108    return -1;
   4.109  }
   4.110  
   4.111 -static int checktag(int tags[],int numtags,int exprtag)
   4.112 +int checktag(int tags[],int numtags,int exprtag)
   4.113  {
   4.114    int i;
   4.115  
   4.116 @@ -2281,12 +2328,8 @@
   4.117                heapalloc+=markheap(MEMUSE_STATIC, 1);
   4.118                nest_stkusage++;
   4.119              } /* if */
   4.120 -          } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION
   4.121 -                     || lval.ident==iARRAYCHAR)
   4.122 +          } else if (lval.ident==iCONSTEXPR || lval.ident==iEXPRESSION)
   4.123            {
   4.124 -            /* fetch value if needed */
   4.125 -            if (lval.ident==iARRAYCHAR)
   4.126 -              rvalue(&lval);
   4.127              /* allocate a cell on the heap and store the
   4.128               * value (already in PRI) there */
   4.129              setheap_pri();        /* address of the value on the heap in PRI */
   4.130 @@ -2297,7 +2340,8 @@
   4.131            /* otherwise, the address is already in PRI */
   4.132            if (lval.sym!=NULL)
   4.133              markusage(lval.sym,uWRITTEN);
   4.134 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
   4.135 +          if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
   4.136 +              && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
   4.137              error(213);
   4.138            if (lval.tag!=0)
   4.139              append_constval(&taglst,arg[argidx].name,lval.tag,0);
   4.140 @@ -2311,14 +2355,15 @@
   4.141            /* otherwise, the expression result is already in PRI */
   4.142            assert(arg[argidx].numtags>0);
   4.143            check_userop(NULL,lval.tag,arg[argidx].tags[0],2,NULL,&lval.tag);
   4.144 -          if (!checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
   4.145 +          if (!checktags_string(arg[argidx].tags, arg[argidx].numtags, &lval)
   4.146 +              && !checktag(arg[argidx].tags,arg[argidx].numtags,lval.tag))
   4.147              error(213);
   4.148            if (lval.tag!=0)
   4.149              append_constval(&taglst,arg[argidx].name,lval.tag,0);
   4.150            argidx++;               /* argument done */
   4.151            break;
   4.152          case iREFERENCE:
   4.153 -          if (!lvalue || lval.ident==iARRAYCHAR)
   4.154 +          if (!lvalue)
   4.155              error(35,argidx+1);   /* argument type mismatch */
   4.156            if (lval.sym!=NULL && (lval.sym->usage & uCONST)!=0 && (arg[argidx].usage & uCONST)==0)
   4.157              error(35,argidx+1);   /* argument type mismatch */
   4.158 @@ -2343,7 +2388,7 @@
   4.159            break;
   4.160          case iREFARRAY:
   4.161            if (lval.ident!=iARRAY && lval.ident!=iREFARRAY
   4.162 -              && lval.ident!=iARRAYCELL)
   4.163 +              && lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR)
   4.164            {
   4.165              error(35,argidx+1);   /* argument type mismatch */
   4.166              break;
   4.167 @@ -2354,7 +2399,7 @@
   4.168             * A literal array always has a single dimension.
   4.169             * An iARRAYCELL parameter is also assumed to have a single dimension.
   4.170             */
   4.171 -          if (lval.sym==NULL || lval.ident==iARRAYCELL) {
   4.172 +          if (lval.sym==NULL || lval.ident==iARRAYCELL || lval.ident==iARRAYCHAR) {
   4.173              if (arg[argidx].numdim!=1) {
   4.174                error(48);        /* array dimensions must match */
   4.175              } else if (arg[argidx].dim[0]!=0) {
   4.176 @@ -2372,14 +2417,14 @@
   4.177                    error(47);      /* array sizes must match */
   4.178                } /* if */
   4.179              } /* if */
   4.180 -            if (lval.ident!=iARRAYCELL) {
   4.181 +            if (lval.ident!=iARRAYCELL && lval.ident!=iARRAYCHAR) {
   4.182                /* save array size, for default values with uSIZEOF flag */
   4.183                cell array_sz=lval.constval;
   4.184                assert(array_sz!=0);/* literal array must have a size */
   4.185                if (array_sz<0)
   4.186                  array_sz= -array_sz;
   4.187                append_constval(&arrayszlst,arg[argidx].name,array_sz,0);
   4.188 -            } /* if */
   4.189 +            }/* if */
   4.190            } else {
   4.191              symbol *sym=lval.sym;
   4.192              short level=0;
   4.193 @@ -2669,6 +2714,7 @@
   4.194                                   * value distinguishes between literal arrays
   4.195                                   * and literal strings (this was done for
   4.196                                   * array assignment). */
   4.197 +	lval->tag=pc_tag_string;
   4.198    } else if (tok=='{') {
   4.199      int tag,lasttag=-1;
   4.200      val=litidx;
     5.1 --- a/sourcepawn/compiler/sc4.c	Tue Nov 07 00:53:06 2006 +0000
     5.2 +++ b/sourcepawn/compiler/sc4.c	Tue Nov 07 09:50:09 2006 +0000
     5.3 @@ -961,12 +961,16 @@
     5.4   * The ALIGN.pri/alt instructions must solve this machine dependence;
     5.5   * that is, on Big Endian computers, ALIGN.pri/alt shuold do nothing
     5.6   * and on Little Endian computers they should toggle the address.
     5.7 + *
     5.8 + * NOTE: For Source Pawn, this is fliped.  It will do nothing on Little-Endian.
     5.9   */
    5.10  SC_FUNC void charalign(void)
    5.11  {
    5.12 +#if 0	/* TEMPORARILY DISABLED BECAUSE WE DON'T USE BIG ENDIAN */
    5.13    stgwrite("\talign.pri ");
    5.14    outval(sCHARBITS/8,TRUE);
    5.15    code_idx+=opcodes(1)+opargs(1);
    5.16 +#endif
    5.17  }
    5.18  
    5.19  /*