decl.c.2
上传用户:upcnvip
上传日期:2007-01-06
资源大小:474k
文件大小:48k
源码类别:

编译器/解释器

开发平台:

C/C++

  1.             return 0;
  2.     }
  3.     if (args) {
  4.         if (mp1->kind == MK_PARAM && mp1->othername)
  5.             tp1 = mp1->rectype;
  6.         if (mp2->kind == MK_PARAM && mp2->othername)
  7.             tp2 = mp2->rectype;
  8.     }
  9.     if (tp1 == tp2)
  10.         return 1;
  11.     switch (mixtypes) {
  12.         case 0:
  13.             return 0;
  14.         case 1:
  15.             return (findbasetype(tp1, flags) == findbasetype(tp2, flags));
  16.         default:
  17.             if (findbasetype(tp1, flags) != findbasetype(tp2, flags))
  18. return 0;
  19.             while (tp1->kind == TK_POINTER && tp1->basetype)
  20.                 tp1 = tp1->basetype;
  21.             while (tp2->kind == TK_POINTER && tp2->basetype)
  22.                 tp2 = tp2->basetype;
  23.             return (tp1 == tp2);
  24.     }
  25. }
  26. void declarefiles(fnames)
  27. Strlist *fnames;
  28. {
  29.     Meaning *mp;
  30.     char *cp;
  31.     while (fnames) {
  32. mp = (Meaning *)fnames->value;
  33. if (mp->kind == MK_VAR || mp->kind == MK_FIELD) {
  34.     if (mp->namedfile) {
  35. output(storageclassname(varstorageclass(mp)));
  36. output(format_ss("%s %s", charname,
  37.  format_s(name_FNVAR, fnames->s)));
  38. output(format_s("[%s];n", *name_FNSIZE ? name_FNSIZE : "80"));
  39.     }
  40.     if (mp->bufferedfile && *declbufname) {
  41. cp = format_s("%s", storageclassname(varstorageclass(mp)));
  42. if (*cp && isspace(cp[strlen(cp)-1]))
  43.   cp[strlen(cp)-1] = 0;
  44. if (*cp || !*declbufncname) {
  45.     output(declbufname);
  46.     output("(");
  47.     output(fnames->s);
  48.     output(",");
  49.     output(cp);
  50. } else {
  51.     output(declbufncname);
  52.     output("(");
  53.     output(fnames->s);
  54. }
  55. output(",");
  56. out_type(mp->type->basetype->basetype, 1);
  57. output(");n");
  58.     }
  59. }
  60. strlist_eat(&fnames);
  61.     }
  62. }
  63. char *variantfieldname(num)
  64. int num;
  65. {
  66.     if (num >= 0)
  67.         return format_d("U%d", num);
  68.     else
  69.         return format_d("UM%d", -num);
  70. }
  71. int record_is_union(tp)
  72. Type *tp;
  73. {
  74.     return (tp->fbase && tp->fbase->kind == MK_VARIANT);
  75. }
  76. void outfieldlist(mp)
  77. Meaning *mp;
  78. {
  79.     Meaning *mp0;
  80.     int num, only_union, empty, saveindent, saveindent2;
  81.     Strlist *fnames, *fn;
  82.     if (!mp) {
  83. output("int empty_struct;   /* Pascal record was empty */n");
  84. return;
  85.     }
  86.     only_union = (mp && mp->kind == MK_VARIANT);
  87.     fnames = NULL;
  88.     while (mp && mp->kind == MK_FIELD) {
  89. flushcomments(&mp->comments, CMT_PRE, -1);
  90. output(storageclassname(varstorageclass(mp) & 0x10));
  91.         outbasetype(mp->type, 0);
  92.         output(" 05");
  93. for (;;) {
  94.     outdeclarator(mp->type, mp->name, 0);
  95.     if (mp->val.i && (mp->type != tp_abyte || mp->val.i != 8))
  96. output(format_d(" : %d", mp->val.i));
  97.     if (isfiletype(mp->type)) {
  98. fn = strlist_append(&fnames, mp->name);
  99. fn->value = (long)mp;
  100.     }
  101.     mp->wasdeclared = 1;
  102.     if (!mp->cnext || mp->cnext->kind != MK_FIELD ||
  103. varstorageclass(mp) != varstorageclass(mp->cnext) ||
  104. !mixable(mp, mp->cnext, 0, 0))
  105. break;
  106.             mp = mp->cnext;
  107.             output(",01 ");
  108.         }
  109.         output(";");
  110. outtrailcomment(mp->comments, -1, declcommentindent);
  111. flushcomments(&mp->comments, -1, -1);
  112.         mp = mp->cnext;
  113.     }
  114.     declarefiles(fnames);
  115.     if (mp) {
  116. saveindent = outindent;
  117. empty = 1;
  118.         if (!only_union) {
  119.             output("union {n");
  120.     moreindent(tabsize);
  121.     moreindent(structindent);
  122.         }
  123.         while (mp) {
  124.             mp0 = mp->ctx;
  125.             num = ord_value(mp->val);
  126.             while (mp && mp->ctx == mp0)
  127.                 mp = mp->cnext;
  128.             if (mp0) {
  129. empty = 0;
  130.                 if (!mp0->cnext && mp0->kind == MK_FIELD) {
  131.                     outfieldlist(mp0);
  132.                 } else {
  133.                     if (mp0->kind == MK_VARIANT)
  134.                         output("union {n");
  135.                     else
  136.                         output("struct {n");
  137.     saveindent2 = outindent;
  138.     moreindent(tabsize);
  139.     moreindent(structindent);
  140.                     outfieldlist(mp0);
  141.     outindent = saveindent2;
  142.                     output("} ");
  143.                     output(format_s(name_VARIANT, variantfieldname(num)));
  144.                     output(";n");
  145.                 }
  146. flushcomments(&mp0->comments, -1, -1);
  147.             }
  148.         }
  149. if (empty)
  150.     output("int empty_union;   /* Pascal variant record was empty */n");
  151.         if (!only_union) {
  152.             outindent = saveindent;
  153.             output("} ");
  154.             output(format_s(name_UNION, ""));
  155.             output(";n");
  156.         }
  157.     }
  158. }
  159. void outbasetype(type, flags)
  160. Type *type;
  161. int flags;
  162. {
  163.     Meaning *mp;
  164.     int saveindent;
  165.     type = findbasetype(type, flags);
  166.     switch (type->kind) {
  167.         case TK_INTEGER:
  168.             if (type == tp_uint) {
  169.                 output("unsigned");
  170.             } else if (type == tp_sint) {
  171.                 if (useAnyptrMacros == 1)
  172.                     output("Signed int");
  173.                 else if (hassignedchar)
  174.                     output("signed int");
  175.                 else
  176.                     output("int");   /* will sign-extend by hand */
  177.             } else if (type == tp_unsigned) {
  178.                 output("unsigned long");
  179.             } else if (type != tp_int)
  180.                 output(integername);
  181.             else
  182.                 output("int");
  183.             break;
  184.         case TK_SUBR:
  185.             if (type == tp_special_anyptr) {
  186.                 output("Anyptr");
  187.             } else if (type == tp_abyte) {
  188.                 output("char");
  189.             } else if (type == tp_ubyte) {
  190.                 output(ucharname);
  191.             } else if (type == tp_sbyte) {
  192.                 output(scharname);
  193.                 if (signedchars != 1 && !hassignedchar)
  194.                     note("'signed char' may not be valid in all compilers [102]");
  195.             } else {
  196.                 if (type == tp_ushort)
  197.                     output("unsigned ");
  198.                 output("short");
  199.             }
  200.             break;
  201.         case TK_CHAR:
  202.             if (type == tp_uchar) {
  203.                 output(ucharname);
  204.             } else if (type == tp_schar) {
  205.                 output(scharname);
  206.                 if (signedchars != 1 && !hassignedchar)
  207.                     note("'signed char' may not be valid in all compilers [102]");
  208.     } else
  209. output(charname);
  210.             break;
  211.         case TK_BOOLEAN:
  212.             output((*name_BOOLEAN) ? name_BOOLEAN : ucharname);
  213.             break;
  214.         case TK_REAL:
  215.     if (type == tp_longreal)
  216. output("double");
  217.     else
  218. output("float");
  219.             break;
  220.         case TK_VOID:
  221.             if (ansiC == 0)
  222.                 output("int");
  223.             else if (useAnyptrMacros == 1)
  224.                 output("Void");
  225.             else
  226.                 output("void");
  227.             break;
  228.         case TK_PROCPTR:
  229.     output(name_PROCEDURE);
  230.     break;
  231.         case TK_FILE:
  232.             output("FILE");
  233.             break;
  234. case TK_SPECIAL:
  235.     if (type == tp_jmp_buf)
  236. output("jmp_buf");
  237.     break;
  238.         default:
  239.             if (type->meaning && type->meaning->kind == MK_TYPE &&
  240.                 type->meaning->wasdeclared) {
  241.                 output(type->meaning->name);
  242.             } else {
  243.                 switch (type->kind) {
  244.                     case TK_ENUM:
  245.                         output("enum {n");
  246. saveindent = outindent;
  247. moreindent(tabsize);
  248. moreindent(structindent);
  249.                         mp = type->fbase;
  250.                         while (mp) {
  251.                             output(mp->name);
  252.                             mp = mp->xnext;
  253.                             if (mp)
  254. output(",01 ");
  255.                         }
  256.                         outindent = saveindent;
  257.                         output("n}");
  258.                         break;
  259.                     case TK_RECORD:
  260.                         if (record_is_union(type))
  261.                             output("union ");
  262.                         else
  263.                             output("struct ");
  264.                         if (type->meaning)
  265.                             output(format_s(name_STRUCT, type->meaning->name));
  266. if (!type->structdefd) {
  267.     if (type->meaning) {
  268. type->structdefd = 1;
  269. output(" ");
  270.     }
  271.                             output("{n");
  272.     saveindent = outindent;
  273.     moreindent(tabsize);
  274.     moreindent(structindent);
  275.                             outfieldlist(type->fbase);
  276.                             outindent = saveindent;
  277.                             output("}");
  278.                         }
  279. break;
  280.     default:
  281. break;
  282.                 }
  283.             }
  284.             break;
  285.     }
  286. }
  287. void out_type(type, witharrays)
  288. Type *type;
  289. int witharrays;
  290. {
  291.     if (!witharrays && type->kind == TK_ARRAY)
  292.         type = makepointertype(type->basetype);
  293.     outbasetype(type, 0);
  294.     outdeclarator(type, "", 0);    /* write an "abstract declarator" */
  295. }
  296. int varstorageclass(mp)
  297. Meaning *mp;
  298. {
  299.     int sclass;
  300.     if (mp->kind == MK_PARAM || mp->kind == MK_VARPARAM ||
  301. mp->kind == MK_FIELD)
  302. sclass = 0;
  303.     else if (blockkind == TOK_EXPORT)
  304.         if (usevextern)
  305.     if (mp->constdefn &&
  306. (mp->kind == MK_VAR ||
  307.  mp->kind == MK_VARREF))
  308. sclass = 2;    /* extern */
  309.     else
  310. sclass = 1;    /* vextern */
  311.         else
  312.             sclass = 0;                         /* (plain) */
  313.     else if (mp->isfunction && mp->kind != MK_FUNCTION)
  314. sclass = 2;   /* extern */
  315.     else if (mp->ctx->kind == MK_MODULE &&
  316.      (var_static != 0 ||
  317.       (findsymbol(mp->name)->flags & NEEDSTATIC)) &&
  318.      !mp->exported && !mp->istemporary && blockkind != TOK_END)
  319.         sclass = (useAnyptrMacros) ? 4 : 3;     /* (private) */
  320.     else if (mp->isforward)
  321.         sclass = 3;   /* static */
  322.     else
  323. sclass = 0;   /* (plain) */
  324.     if (mp->volatilequal)
  325. sclass |= 0x10;
  326.     if (mp->constqual)
  327. sclass |= 0x20;
  328.     if (debug>2) fprintf(outf, "varstorageclass(%s) = %dn", mp->name, sclass);
  329.     return sclass;
  330. }
  331. char *storageclassname(i)
  332. int i;
  333. {
  334.     char *scname;
  335.     switch (i & 0xf) {
  336.         case 1:
  337.             scname = "vextern ";
  338.     break;
  339.         case 2:
  340.             scname = "extern ";
  341.     break;
  342.         case 3:
  343.             scname = "static ";
  344.     break;
  345.         case 4:
  346.             scname = "Static ";
  347.     break;
  348.         default:
  349.             scname = "";
  350.     break;
  351.     }
  352.     if (i & 0x10)
  353. if (useAnyptrMacros == 1)
  354.     scname = format_s("%sVolatile ", scname);
  355. else if (ansiC > 0)
  356.     scname = format_s("%svolatile ", scname);
  357.     if (i & 0x20)
  358. if (useAnyptrMacros == 1)
  359.     scname = format_s("%sConst ", scname);
  360. else if (ansiC > 0)
  361.     scname = format_s("%sconst ", scname);
  362.     return scname;
  363. }
  364. void declarevar(mp, which)
  365. Meaning *mp;
  366. int which;    /* 0x1=header, 0x2=body, 0x4=trailer, 0x8=in varstruct */
  367. {
  368.     int isstatic, isstructconst, saveindent;
  369.     isstructconst = checkstructconst(mp);
  370.     isstatic = varstorageclass(mp);
  371.     if (which & 0x8)
  372. isstatic &= 0x10;   /* clear all but Volatile flags */
  373.     flushcomments(&mp->comments, CMT_PRE, -1);
  374.     if (which & 0x1) {
  375.         if (isstructconst)
  376.             outsection(minorspace);
  377.         output(storageclassname(isstatic));
  378.         outbasetype(mp->type, 0);
  379.         output(" 05");
  380.     }
  381.     if (which & 0x2) {
  382.         outdeclarator(mp->type, mp->name, 0);
  383.         if (mp->constdefn && blockkind != TOK_EXPORT &&
  384.     (mp->kind == MK_VAR || mp->kind == MK_VARREF)) {
  385.             if (mp->varstructflag) {    /* move init code into function body */
  386.                 intwarning("declarevar",
  387.                     format_s("Variable %s initializer not removed [125]", mp->name));
  388.             } else {
  389.                 output(" = ");
  390.                 if (isstructconst) {
  391.                     output("{n");
  392.     saveindent = outindent;
  393.     moreindent(tabsize);
  394.     moreindent(structinitindent);
  395.                     out_expr((Expr *)mp->constdefn->val.i);
  396.                     outindent = saveindent;
  397.                     output("n}");
  398.                 } else
  399.                     out_expr(mp->constdefn);
  400.             }
  401.         }
  402.     }
  403.     if (which & 0x4) {
  404.         output(";");
  405. outtrailcomment(mp->comments, -1, declcommentindent);
  406. flushcomments(&mp->comments, -1, -1);
  407.         if (isstructconst)
  408.             outsection(minorspace);
  409.     }
  410. }
  411. Static int checkvarmacdef(ex, mp)
  412. Expr *ex;
  413. Meaning *mp;
  414. {
  415.     int i;
  416.     if ((ex->kind == EK_NAME || ex->kind == EK_BICALL) &&
  417. !strcmp(ex->val.s, mp->name)) {
  418. ex->kind = EK_VAR;
  419. ex->val.i = (long)mp;
  420. ex->val.type = mp->type;
  421. return 1;
  422.     }
  423.     if (ex->kind == EK_VAR && ex->val.i == (long)mp)
  424. return 1;
  425.     i = ex->nargs;
  426.     while (--i >= 0)
  427. if (checkvarmacdef(ex->args[i], mp))
  428.     return 1;
  429.     return 0;
  430. }
  431. int checkvarmac(mp)
  432. Meaning *mp;
  433. {
  434.     if (mp->kind != MK_VARMAC && mp->kind != MK_FUNCTION)
  435. return 0;
  436.     if (!mp->constdefn)
  437. return 0;
  438.     return checkvarmacdef(mp->constdefn, mp);
  439. }
  440. #define varkind(k) ((k)==MK_VAR||(k)==MK_VARREF||(k)==MK_PARAM||(k)==MK_VARPARAM)
  441. int declarevars(ctx, invarstruct)
  442. Meaning *ctx;
  443. int invarstruct;
  444. {
  445.     Meaning *mp, *mp0, *mp2;
  446.     Strlist *fnames, *fn;
  447.     int flag, first;
  448.     if (ctx->kind == MK_FUNCTION && ctx->varstructflag && !invarstruct) {
  449.         output("struct ");
  450.         output(format_s(name_LOC, ctx->name));
  451.         output(" ");
  452.         output(format_s(name_VARS, ctx->name));
  453.         output(";n");
  454.         flag = 1;
  455.     } else
  456.         flag = 0;
  457.     if (debug>2) {
  458.         fprintf(outf,"declarevars:n");
  459.         for (mp = ctx->cbase; mp; mp = mp->xnext) {
  460.             fprintf(outf, "  %-22s%-15s%3d", mp->name,
  461.                                              meaningkindname(mp->kind),
  462.                                              mp->refcount);
  463.             if (mp->wasdeclared)
  464.                 fprintf(outf, " [decl]");
  465.             if (mp->varstructflag)
  466.                 fprintf(outf, " [struct]");
  467.             fprintf(outf, "n");
  468.         }
  469.     }
  470.     fnames = NULL;
  471.     for (;;) {
  472.         mp = ctx->cbase;
  473.         while (mp && (!(varkind(mp->kind) || checkvarmac(mp)) ||
  474.       mp->wasdeclared || mp->varstructflag != invarstruct ||
  475.       mp->refcount <= 0))
  476.             mp = mp->cnext;
  477.         if (!mp)
  478.             break;
  479.         flag = 1;
  480.         first = 1;
  481.         mp0 = mp2 = mp;
  482.         while (mp) {
  483.             if ((varkind(mp->kind) || checkvarmac(mp)) &&
  484. !mp->wasdeclared &&
  485.                 varstorageclass(mp) == varstorageclass(mp0) &&
  486.                 mp->varstructflag == invarstruct && mp->refcount > 0) {
  487.                 if (mixable(mp2, mp, 0, 0) || first) {
  488.                     if (!first)
  489.                         output(",01 ");
  490.                     declarevar(mp, (first ? 0x3 : 0x2) |
  491.            (invarstruct ? 0x8 : 0));
  492.     mp2 = mp;
  493.                     mp->wasdeclared = 1;
  494.                     if (isfiletype(mp->type)) {
  495.                         fn = strlist_append(&fnames, mp->name);
  496.                         fn->value = (long)mp;
  497.                     }
  498.                     first = 0;
  499.                 } else
  500.                     if (mixvars != 1)
  501.                         break;
  502.             }
  503.     if (first) {
  504. intwarning("declarevars",
  505.    format_s("Unable to declare %s [126]", mp->name));
  506. mp->wasdeclared = 1;
  507. first = 0;
  508.     }
  509.             if (mixvars == 0)
  510.                 break;
  511.             mp = mp->cnext;
  512.         }
  513.         declarevar(mp2, 0x4);
  514.     }
  515.     declarefiles(fnames);
  516.     return flag;
  517. }
  518. void redeclarevars(ctx)
  519. Meaning *ctx;
  520. {
  521.     Meaning *mp;
  522.     for (mp = ctx->cbase; mp; mp = mp->cnext) {
  523.         if ((mp->kind == MK_VAR || mp->kind == MK_VARREF) &&
  524.             mp->constdefn) {
  525.             mp->wasdeclared = 0;    /* mark for redeclaration, this time */
  526.         }                           /*  with its initializer */
  527.     }
  528. }
  529. void out_argdecls(ftype)
  530. Type *ftype;
  531. {
  532.     Meaning *mp, *mp0;
  533.     Type *tp;
  534.     int done;
  535.     int flag = 1;
  536.     char *name;
  537.     done = 0;
  538.     do {
  539.         mp = ftype->fbase;
  540.         while (mp && mp->wasdeclared)
  541.             mp = mp->xnext;
  542.         if (mp) {
  543.             if (flag)
  544.                 output("n");
  545.             flag = 0;
  546.             mp0 = mp;
  547.             outbasetype(mp->othername ? mp->rectype : mp->type,
  548. ODECL_CHARSTAR|ODECL_FREEARRAY);
  549.             output(" 05");
  550.             while (mp) {
  551.                 if (!mp->wasdeclared) {
  552.                     if (mp == mp0 ||
  553. mixable(mp0, mp, 1, ODECL_CHARSTAR|ODECL_FREEARRAY)) {
  554.                         if (mp != mp0)
  555.                             output(",01 ");
  556.                         name = (mp->othername) ? mp->othername : mp->name;
  557.                         tp = (mp->othername) ? mp->rectype : mp->type;
  558.                         outdeclarator(tp, name,
  559.       ODECL_CHARSTAR|ODECL_FREEARRAY);
  560.                         mp->wasdeclared = 1;
  561.                     } else
  562.                         if (mixvars != 1)
  563.                             break;
  564.                 }
  565.                 mp = mp->xnext;
  566.             }
  567.             output(";n");
  568.         } else
  569.             done = 1;
  570.     } while (!done);
  571.     for (mp0 = ftype->fbase; mp0 && (mp0->type != tp_strptr ||
  572.                                      !mp0->anyvarflag); mp0 = mp0->xnext) ;
  573.     if (mp0) {
  574.         output("int ");
  575.         for (mp = mp0; mp; mp = mp->xnext) {
  576.             if (mp->type == tp_strptr && mp->anyvarflag) {
  577.                 if (mp != mp0) {
  578.                     if (mixvars == 0)
  579.                         output(";nint ");
  580.                     else
  581.                         output(",01 ");
  582.                 }
  583.                 output(format_s(name_STRMAX, mp->name));
  584.             }
  585.         }
  586.         output(";n");
  587.     }
  588.     if (ftype->meaning && ftype->meaning->ctx->kind == MK_FUNCTION &&
  589.                           ftype->meaning->ctx->varstructflag) {
  590.         if (flag)
  591.             output("n");
  592.         output("struct ");
  593.         output(format_s(name_LOC, ftype->meaning->ctx->name));
  594.         output(" *");
  595.         output(format_s(name_LINK, ftype->meaning->ctx->name));
  596.         output(";n");
  597.     }
  598. }
  599. void makevarstruct(func)
  600. Meaning *func;
  601. {
  602.     int flag = 0;
  603.     int saveindent;
  604.     outsection(minfuncspace);
  605.     output(format_s("n/* Local variables for %s: */n", func->name));
  606.     output("struct ");
  607.     output(format_s(name_LOC, func->name));
  608.     output(" {n");
  609.     saveindent = outindent;
  610.     moreindent(tabsize);
  611.     moreindent(structindent);
  612.     if (func->ctx->kind == MK_FUNCTION && func->ctx->varstructflag) {
  613.         output("struct ");
  614.         output(format_s(name_LOC, func->ctx->name));
  615.         output(" *");
  616.         output(format_s(name_LINK, func->ctx->name));
  617.         output(";n");
  618.         flag++;
  619.     }
  620.     flag += declarevars(func, 1);
  621.     if (!flag)                       /* Avoid generating an empty struct */
  622.         output("int _meef_;n");     /* (I don't think this will ever happen) */
  623.     outindent = saveindent;
  624.     output("} ;n");
  625.     outsection(minfuncspace);
  626.     strlist_insert(&varstructdecllist, func->name);
  627. }
  628. Type *maketype(kind)
  629. enum typekind kind;
  630. {
  631.     Type *tp;
  632.     tp = ALLOC(1, Type, types);
  633.     tp->kind = kind;
  634.     tp->basetype = NULL;
  635.     tp->indextype = NULL;
  636.     tp->pointertype = NULL;
  637.     tp->meaning = NULL;
  638.     tp->fbase = NULL;
  639.     tp->smin = NULL;
  640.     tp->smax = NULL;
  641.     tp->issigned = 0;
  642.     tp->dumped = 0;
  643.     tp->structdefd = 0;
  644.     return tp;
  645. }
  646. Type *makesubrangetype(type, smin, smax)
  647. Type *type;
  648. Expr *smin, *smax;
  649. {
  650.     Type *tp;
  651.     if (type->kind == TK_SUBR)
  652.         type = type->basetype;
  653.     tp = maketype(TK_SUBR);
  654.     tp->basetype = type;
  655.     tp->smin = smin;
  656.     tp->smax = smax;
  657.     return tp;
  658. }
  659. Type *makesettype(setof)
  660. Type *setof;
  661. {
  662.     Type *tp;
  663.     long smax;
  664.     if (ord_range(setof, NULL, &smax) && smax < setbits && smallsetconst >= 0)
  665.         tp = maketype(TK_SMALLSET);
  666.     else
  667.         tp = maketype(TK_SET);
  668.     tp->basetype = tp_integer;
  669.     tp->indextype = setof;
  670.     return tp;
  671. }
  672. Type *makestringtype(len)
  673. int len;
  674. {
  675.     Type *type;
  676.     int index;
  677.     len |= 1;
  678.     if (len >= stringceiling)
  679.         type = tp_str255;
  680.     else {
  681.         index = (len-1) / 2;
  682.         if (stringtypecache[index])
  683.             return stringtypecache[index];
  684.         type = maketype(TK_STRING);
  685.         type->basetype = tp_char;
  686.         type->indextype = makesubrangetype(tp_integer, 
  687.                                            makeexpr_long(0), 
  688.                                            makeexpr_long(len));
  689.         stringtypecache[index] = type;
  690.     }
  691.     return type;
  692. }
  693. Type *makepointertype(type)
  694. Type *type;
  695. {
  696.     Type *tp;
  697.     if (type->pointertype)
  698.         return type->pointertype;
  699.     tp = maketype(TK_POINTER);
  700.     tp->basetype = type;
  701.     type->pointertype = tp;
  702.     return tp;
  703. }
  704. Value p_constant(type)
  705. Type *type;
  706. {
  707.     Value val;
  708.     Expr *ex;
  709.     ex = p_expr(type);
  710.     if (type)
  711.         ex = gentle_cast(ex, type);
  712.     val = eval_expr(ex);
  713.     freeexpr(ex);
  714.     if (!val.type) {
  715.         warning("Expected a constant [127]");
  716.         val.type = (type) ? type : tp_integer;
  717.     }
  718.     return val;
  719. }
  720. int typebits(smin, smax)
  721. long smin, smax;
  722. {
  723.     unsigned long size;
  724.     int bits;
  725.     if (smin >= 0 || (smin == -1 && smax == 0)) {
  726.         bits = 1;
  727.         size = smax;
  728.     } else {
  729.         bits = 2;
  730.         smin = -1L - smin;
  731.         if (smin >= smax)
  732.             size = smin;
  733.         else
  734.             size = smax;
  735.     }
  736.     while (size > 1) {
  737.         bits++;
  738.         size >>= 1;
  739.     }
  740.     return bits;
  741. }
  742. int packedsize(fname, typep, sizep, mode)
  743. char *fname;
  744. Type **typep;
  745. long *sizep;
  746. int mode;
  747. {
  748.     Type *tp = *typep;
  749.     long smin, smax;
  750.     int res, issigned;
  751.     short savefold;
  752.     long size;
  753.     if (packing == 0)   /* suppress packing */
  754.         return 0;
  755.     if (tp->kind != TK_SUBR && tp->kind != TK_INTEGER && tp->kind != TK_ENUM &&
  756.         tp->kind != TK_CHAR && tp->kind != TK_BOOLEAN)
  757.         return 0;
  758.     if (tp == tp_unsigned)
  759. return 0;
  760.     if (!ord_range(tp, &smin, &smax)) {
  761.         savefold = foldconsts;
  762.         foldconsts = 1;
  763.         res = ord_range(tp, &smin, &smax);
  764.         foldconsts = savefold;
  765.         if (res) {
  766.             note(format_s("Field width for %s is based on expansion of #defines [103]",
  767.                           fname));
  768.         } else {
  769.             note(format_ss("Cannot compute size of field %s; assuming %s [104]",
  770.                            fname, integername));
  771.             return 0;
  772.         }
  773.     } else {
  774.         if (tp->kind == TK_ENUM)
  775.             note(format_ssd("Field width for %s assumes enum%s has %d elements [105]",
  776.                             fname,
  777.                             (tp->meaning) ? format_s(" %s", tp->meaning->name) : "",
  778.                             smax + 1));
  779.     }
  780.     issigned = (smin < 0);
  781.     size = typebits(smin, smax);
  782.     if (size >= ((sizeof_long > 0) ? sizeof_long : 32))
  783.         return 0;
  784.     if (packing != 1) {
  785.         if (size <= 8)
  786.             size = 8;
  787.         else if (size <= 16)
  788.             size = 16;
  789.         else
  790.             return 0;
  791.     }
  792.     if (!issigned) {
  793.         *typep = (mode == 0) ? tp_int : tp_uint;
  794.     } else {
  795.         if (mode == 2 && !hassignedchar && !*signextname)
  796.             return 0;
  797.         *typep = (mode == 1) ? tp_int : tp_sint;
  798.     }
  799.     *sizep = size;
  800.     return issigned;
  801. }
  802. Static void fielddecl(mp, type, tp2, val, ispacked, aligned)
  803. Meaning *mp;
  804. Type **type, **tp2;
  805. long *val;
  806. int ispacked, *aligned;
  807. {
  808.     long smin, smax, smin2, smax2;
  809.     *tp2 = *type;
  810.     *val = 0;
  811.     if (ispacked && !mp->constdefn && *type != tp_unsigned) {
  812.         (void)packedsize(mp->sym->name, tp2, val, signedfield);
  813.         if (*aligned && *val &&
  814.             (ord_type(*type)->kind == TK_CHAR ||
  815.              ord_type(*type)->kind == TK_INTEGER) &&
  816.             ord_range(findbasetype(*type, 0), &smin, &smax)) {
  817.     if (ord_range(*type, &smin2, &smax2)) {
  818. if (typebits(smin, smax) == 16 &&
  819.     typebits(smin2, smax2) == 8 && *val == 8) {
  820.     *tp2 = tp_abyte;
  821. }
  822.     }
  823.     if (typebits(smin, smax) == *val &&
  824. *val != 7) {    /* don't be fooled by tp_abyte */
  825. /* don't need to use a bit-field for this field */
  826. /* so not specifying one may make it more efficient */
  827. /* (and also helps to simulate HP's $allow_packed$ mode) */
  828. *val = 0;
  829. *tp2 = *type;
  830.     } 
  831.         }
  832.         if (*aligned && *val == 8 &&
  833.             (ord_type(*type)->kind == TK_BOOLEAN ||
  834.              ord_type(*type)->kind == TK_ENUM)) {
  835.             *val = 0;
  836.             *tp2 = tp_ubyte;
  837.         }
  838.     }
  839.     if (*val != 8 && *val != 16)
  840. *aligned = (*val == 0);
  841. }
  842. /* This function locates byte-sized fields which were unaligned, but which
  843.    are followed by aligned quantities so that they can be made aligned
  844.    with no loss in storage efficiency. */
  845. Static void realignfields(firstmp, stopmp)
  846. Meaning *firstmp, *stopmp;
  847. {
  848.     Meaning *mp;
  849.     for (mp = firstmp; mp && mp != stopmp; mp = mp->cnext) {
  850. if (mp->kind == MK_FIELD) {
  851.     if (mp->val.i == 16) {
  852. if (mp->type == tp_uint)
  853.     mp->type = tp_ushort;
  854. else
  855.     mp->type = tp_sshort;
  856. mp->val.i = 0;
  857.     } else if (mp->val.i == 8) {
  858. if (mp->type == tp_uint) {
  859.     mp->type = tp_ubyte;
  860.     mp->val.i = 0;
  861. } else if (hassignedchar || signedchars == 1) {
  862.     mp->type = tp_sbyte;
  863.     mp->val.i = 0;
  864. } else
  865.     mp->type = tp_abyte;
  866.     }
  867. }
  868.     }
  869. }
  870. static void tryrealignfields(firstmp)
  871. Meaning *firstmp;
  872. {
  873.     Meaning *mp, *head;
  874.     head = NULL;
  875.     for (mp = firstmp; mp; mp = mp->cnext) {
  876. if (mp->kind == MK_FIELD) {
  877.     if (mp->val.i == 8 || mp->val.i == 16) {
  878. if (!head)
  879.     head = mp;
  880.     } else {
  881. if (mp->val.i == 0)
  882.     realignfields(head, mp);
  883. head = NULL;
  884.     }
  885. }
  886.     }
  887.     realignfields(head, NULL);
  888. }
  889. void decl_comments(mp)
  890. Meaning *mp;
  891. {
  892.     Strlist *cmt;
  893.     if (spitcomments != 1) {
  894. changecomments(curcomments, -1, -1, CMT_PRE, 0);
  895. strlist_mix(&mp->comments, curcomments);
  896. curcomments = NULL;
  897. cmt = grabcomment(CMT_TRAIL);
  898. if (cmt) {
  899.     changecomments(mp->comments, CMT_TRAIL, -1, CMT_PRE, -1);
  900.     strlist_mix(&mp->comments, cmt);
  901. }
  902. if (mp->comments)
  903.     mp->refcount++;   /* force it to be included if it has comments */
  904.     }
  905. }
  906. Static void p_fieldlist(tp, flast, ispacked, tname)
  907. Type *tp;
  908. Meaning **flast;
  909. int ispacked;
  910. Meaning *tname;
  911. {
  912.     Meaning *firstm, *lastm, *veryfirstm;
  913.     Symbol *sym;
  914.     Type *type, *tp2;
  915.     long li1, li2;
  916.     int aligned, constflag, volatileflag;
  917.     short saveskipind;
  918.     Strlist *l1;
  919.     saveskipind = skipindices;
  920.     skipindices = 0;
  921.     aligned = 1;
  922.     lastm = NULL;
  923.     veryfirstm = NULL;
  924.     while (curtok == TOK_IDENT) {
  925.         firstm = addfield(curtoksym, &flast, tp, tname);
  926. if (!veryfirstm)
  927.     veryfirstm = firstm;
  928.         lastm = firstm;
  929.         gettok();
  930. decl_comments(lastm);
  931.         while (curtok == TOK_COMMA) {
  932.             gettok();
  933.             if (wexpecttok(TOK_IDENT))
  934. lastm = addfield(curtoksym, &flast, tp, tname);
  935.             gettok();
  936.     decl_comments(lastm);
  937.         }
  938.         if (wneedtok(TOK_COLON)) {
  939.     constflag = volatileflag = 0;
  940.     p_attributes();
  941.     if ((l1 = strlist_find(attrlist, "READONLY")) != NULL) {
  942. constflag = 1;
  943. strlist_delete(&attrlist, l1);
  944.     }
  945.     if ((l1 = strlist_find(attrlist, "VOLATILE")) != NULL) {
  946. volatileflag = 1;
  947. strlist_delete(&attrlist, l1);
  948.     }
  949.     type = p_type(firstm);
  950.     decl_comments(lastm);
  951.     fielddecl(firstm, &type, &tp2, &li1, ispacked, &aligned);
  952.     for (;;) {
  953. firstm->type = tp2;
  954. firstm->val.type = type;
  955. firstm->val.i = li1;
  956. firstm->constqual = constflag;
  957. firstm->volatilequal = volatileflag;
  958. tp->meaning = tname;
  959. setupfilevar(firstm);
  960. tp->meaning = NULL;
  961. if (firstm == lastm)
  962.     break;
  963. firstm = firstm->cnext;
  964.     }
  965. } else
  966.     skiptotoken2(TOK_SEMI, TOK_CASE);
  967.         if (curtok == TOK_SEMI)
  968.             gettok();
  969.     }
  970.     if (curtok == TOK_CASE) {
  971.         gettok();
  972. if (curtok == TOK_COLON)
  973.     gettok();
  974. wexpecttok(TOK_IDENT);
  975. sym = curtoksym;
  976. if (curtokmeaning)
  977.     type = curtokmeaning->type;
  978. gettok();
  979.         if (curtok == TOK_COLON) {
  980.             firstm = addfield(sym, &flast, tp, tname);
  981.     if (!veryfirstm)
  982. veryfirstm = firstm;
  983.             gettok();
  984.     firstm->isforward = 1;
  985.             firstm->val.type = type = p_type(firstm);
  986.             fielddecl(firstm, &firstm->val.type, &firstm->type, &firstm->val.i, 
  987.                       ispacked, &aligned);
  988.         } else {
  989.     firstm = NULL;
  990. }
  991.         if (!wneedtok(TOK_OF)) {
  992.     skiptotoken2(TOK_END, TOK_RPAR);
  993.     goto bounce;
  994. }
  995. if (firstm)
  996.     decl_comments(firstm);
  997. while (curtok == TOK_VBAR)
  998.     gettok();
  999.         while (curtok != TOK_END && curtok != TOK_RPAR) {
  1000.             firstm = NULL;
  1001.             for (;;) {
  1002. lastm = addfield(NULL, &flast, tp, tname);
  1003. if (!firstm)
  1004.     firstm = lastm;
  1005. checkkeyword(TOK_OTHERWISE);
  1006. if (curtok == TOK_ELSE || curtok == TOK_OTHERWISE) {
  1007.     lastm->val = make_ord(type, 999);
  1008.     break;
  1009. } else {
  1010.     lastm->val = p_constant(type);
  1011.     if (curtok == TOK_DOTS) {
  1012. gettok();
  1013. li1 = ord_value(lastm->val);
  1014. li2 = ord_value(p_constant(type));
  1015. while (++li1 <= li2) {
  1016.     lastm = addfield(NULL, &flast, tp, tname);
  1017.     lastm->val = make_ord(type, li1);
  1018. }
  1019.     }
  1020. }
  1021.                 if (curtok == TOK_COMMA)
  1022.                     gettok();
  1023.                 else
  1024.                     break;
  1025.             }
  1026.     if (curtok == TOK_ELSE || curtok == TOK_OTHERWISE) {
  1027. gettok();
  1028.             } else if (!wneedtok(TOK_COLON) ||
  1029.      (!modula2 && !wneedtok(TOK_LPAR))) {
  1030. skiptotoken2(TOK_END, TOK_RPAR);
  1031. goto bounce;
  1032.     }
  1033.             p_fieldlist(tp, &lastm->ctx, ispacked, tname);
  1034.             while (firstm != lastm) {
  1035.                 firstm->ctx = lastm->ctx;
  1036.                 firstm = firstm->cnext;
  1037.             }
  1038.     if (modula2) {
  1039. while (curtok == TOK_VBAR)
  1040.     gettok();
  1041.     } else {
  1042. if (!wneedtok(TOK_RPAR))
  1043.     skiptotoken(TOK_RPAR);
  1044.     }
  1045.             if (curtok == TOK_SEMI)
  1046.                 gettok();
  1047.         }
  1048. if (modula2) {
  1049.     wneedtok(TOK_END);
  1050.     if (curtok == TOK_IDENT) {
  1051. note("Record variants supported only at end of record [106]");
  1052. p_fieldlist(tp, &lastm->ctx, ispacked, tname);
  1053.     }
  1054. }
  1055.     }
  1056.     tryrealignfields(veryfirstm);
  1057.     if (lastm && curtok == TOK_END) {
  1058. strlist_mix(&lastm->comments, curcomments);
  1059. curcomments = NULL;
  1060.     }
  1061.   bounce:
  1062.     skipindices = saveskipind;
  1063. }
  1064. Static Type *p_arraydecl(tname, ispacked, confp)
  1065. char *tname;
  1066. int ispacked;
  1067. Meaning ***confp;
  1068. {
  1069.     Type *tp, *tp2;
  1070.     Meaning *mp;
  1071.     long size, smin, smax, bitsize, fullbitsize;
  1072.     int issigned, bpower, hasrange;
  1073.     tp = maketype(TK_ARRAY);
  1074.     if (confp == NULL) {
  1075. tp->indextype = p_type(NULL);
  1076. if (tp->indextype->kind == TK_SUBR) {
  1077.     if (ord_range(tp->indextype, &smin, NULL) &&
  1078. smin > 0 && smin <= skipindices && !ispacked) {
  1079. tp->smin = makeexpr_val(make_ord(tp->indextype->basetype, smin));
  1080. tp->indextype = makesubrangetype(tp->indextype->basetype,
  1081.  makeexpr_val(make_ord(
  1082.              tp->indextype->basetype, 0)),
  1083.  copyexpr(tp->indextype->smax));
  1084.     }
  1085. }
  1086.     } else {
  1087. if (modula2) {
  1088.     **confp = mp = addmeaning(findsymbol(format_s(name_ALOW, tname)), MK_PARAM);
  1089.     mp->fakeparam = 1;
  1090.     mp->constqual = 1;
  1091.     mp->xnext = addmeaning(findsymbol(format_s(name_AHIGH, tname)), MK_PARAM);
  1092.     mp->xnext->fakeparam = 1;
  1093.     mp->xnext->constqual = 1;
  1094.     *confp = &mp->xnext->xnext;
  1095.     tp2 = maketype(TK_SUBR);
  1096.     tp2->basetype = tp_integer;
  1097.     mp->type = tp_integer;
  1098.     mp->xnext->type = mp->type;
  1099.     tp2->smin = makeexpr_long(0);
  1100.     tp2->smax = makeexpr_minus(makeexpr_var(mp->xnext),
  1101.        makeexpr_var(mp));
  1102.     tp->indextype = tp2;
  1103.     tp->structdefd = 1;
  1104. } else {
  1105.     wexpecttok(TOK_IDENT);
  1106.     tp2 = maketype(TK_SUBR);
  1107.     if (peeknextchar() != ',' &&
  1108. (!curtokmeaning || curtokmeaning->kind != MK_TYPE)) {
  1109. mp = addmeaning(curtoksym, MK_PARAM);
  1110. gettok();
  1111. wneedtok(TOK_DOTS);
  1112. wexpecttok(TOK_IDENT);
  1113. mp->xnext = addmeaning(curtoksym, MK_PARAM);
  1114. gettok();
  1115. if (wneedtok(TOK_COLON)) {
  1116.     tp2->basetype = p_type(NULL);
  1117. } else {
  1118.     tp2->basetype = tp_integer;
  1119. }
  1120.     } else {
  1121. mp = addmeaning(findsymbol(format_s(name_ALOW, tname)), MK_PARAM);
  1122. mp->xnext = addmeaning(findsymbol(format_s(name_AHIGH, tname)), MK_PARAM);
  1123. tp2->basetype = p_type(NULL);
  1124.     }
  1125.     mp->fakeparam = 1;
  1126.     mp->constqual = 1;
  1127.     mp->xnext->fakeparam = 1;
  1128.     mp->xnext->constqual = 1;
  1129.     **confp = mp;
  1130.     *confp = &mp->xnext->xnext;
  1131.     mp->type = tp2->basetype;
  1132.     mp->xnext->type = tp2->basetype;
  1133.     tp2->smin = makeexpr_var(mp);
  1134.     tp2->smax = makeexpr_var(mp->xnext);
  1135.     tp->indextype = tp2;
  1136.     tp->structdefd = 1;     /* conformant array flag */
  1137. }
  1138.     }
  1139.     if (curtok == TOK_COMMA || curtok == TOK_SEMI) {
  1140.         gettok();
  1141.         tp->basetype = p_arraydecl(tname, ispacked, confp);
  1142.         return tp;
  1143.     } else {
  1144. if (!modula2) {
  1145.     if (!wneedtok(TOK_RBR))
  1146. skiptotoken(TOK_OF);
  1147. }
  1148.         if (!wneedtok(TOK_OF))
  1149.     skippasttotoken(TOK_OF, TOK_COMMA);
  1150. checkkeyword(TOK_VARYING);
  1151. if (confp != NULL &&
  1152.     (curtok == TOK_ARRAY || curtok == TOK_PACKED ||
  1153.      curtok == TOK_VARYING)) {
  1154.     tp->basetype = p_conformant_array(tname, confp);
  1155. } else
  1156.     tp->basetype = p_type(NULL);
  1157.         if (!ispacked)
  1158.             return tp;
  1159.         size = 0;
  1160.         tp2 = tp->basetype;
  1161.         if (!tname)
  1162.             tname = "array";
  1163.         issigned = packedsize(tname, &tp2, &size, 1);
  1164.         if (!size || size > 8 ||
  1165.             (issigned && !packsigned) ||
  1166.             (size > 4 &&
  1167.              (!issigned || (signedchars == 1 || hassignedchar))))
  1168.             return tp;
  1169.         bpower = 0;
  1170.         while ((1<<bpower) < size)
  1171.             bpower++;        /* round size up to power of two */
  1172.         size = 1<<bpower;    /* size = # bits in an array element */
  1173.         tp->escale = bpower;
  1174.         tp->issigned = issigned;
  1175.         hasrange = ord_range(tp->indextype, &smin, &smax) &&
  1176.                    (smax < 100000);    /* don't be confused by giant arrays */
  1177.         if (hasrange &&
  1178.     (bitsize = (smax - smin + 1) * size)
  1179.         <= ((sizeof_integer > 0) ? sizeof_integer : 32)) {
  1180.             if (bitsize > ((sizeof_short > 0) ? sizeof_short : 16)) {
  1181.                 tp2 = (issigned) ? tp_integer : tp_unsigned;
  1182.                 fullbitsize = ((sizeof_integer > 0) ? sizeof_integer : 32);
  1183.             } else if (bitsize > ((sizeof_char > 0) ? sizeof_char : 8) ||
  1184.                        (issigned && !(signedchars == 1 || hassignedchar))) {
  1185.                 tp2 = (issigned) ? tp_sshort : tp_ushort;
  1186.                 fullbitsize = ((sizeof_short > 0) ? sizeof_short : 16);
  1187.             } else {
  1188.                 tp2 = (issigned) ? tp_sbyte : tp_ubyte;
  1189.                 fullbitsize = ((sizeof_char > 0) ? sizeof_char : 8);
  1190.             }
  1191.             tp->kind = TK_SMALLARRAY;
  1192.             if (ord_range(tp->indextype, &smin, NULL) &&
  1193.                 smin > 0 && smin <= fullbitsize - bitsize) {
  1194.                 tp->smin = makeexpr_val(make_ord(tp->indextype->basetype, smin));
  1195.                 tp->indextype = makesubrangetype(tp->indextype->basetype,
  1196.                                                  makeexpr_val(make_ord(
  1197.                                                      tp->indextype->basetype, 0)),
  1198.                                                  copyexpr(tp->indextype->smax));
  1199.             }
  1200.         } else {
  1201.             if (!issigned)
  1202.                 tp2 = tp_ubyte;
  1203.             else if (signedchars == 1 || hassignedchar)
  1204.                 tp2 = tp_sbyte;
  1205.             else
  1206.                 tp2 = tp_sshort;
  1207.         }
  1208.         tp->smax = makeexpr_type(tp->basetype);
  1209.         tp->basetype = tp2;
  1210.         return tp;
  1211.     }
  1212. }
  1213. Static Type *p_conformant_array(tname, confp)
  1214. char *tname;
  1215. Meaning ***confp;
  1216. {
  1217.     int ispacked;
  1218.     Meaning *mp;
  1219.     Type *tp, *tp2;
  1220.     p_attributes();
  1221.     ignore_attributes();
  1222.     if (curtok == TOK_PACKED) {
  1223. ispacked = 1;
  1224. gettok();
  1225.     } else
  1226. ispacked = 0;
  1227.     checkkeyword(TOK_VARYING);
  1228.     if (curtok == TOK_VARYING) {
  1229. gettok();
  1230. wneedtok(TOK_LBR);
  1231. wexpecttok(TOK_IDENT);
  1232. mp = addmeaning(curtoksym, MK_PARAM);
  1233. mp->fakeparam = 1;
  1234. mp->constqual = 1;
  1235. **confp = mp;
  1236. *confp = &mp->xnext;
  1237. mp->type = tp_integer;
  1238. tp2 = maketype(TK_SUBR);
  1239. tp2->basetype = tp_integer;
  1240. tp2->smin = makeexpr_long(1);
  1241. tp2->smax = makeexpr_var(mp);
  1242. tp = maketype(TK_STRING);
  1243. tp->indextype = tp2;
  1244. tp->basetype = tp_char;
  1245. tp->structdefd = 1;     /* conformant array flag */
  1246. gettok();
  1247. wneedtok(TOK_RBR);
  1248. skippasttoken(TOK_OF);
  1249. tp->basetype = p_type(NULL);
  1250. return tp;
  1251.     }
  1252.     if (wneedtok(TOK_ARRAY) &&
  1253. (modula2 || wneedtok(TOK_LBR))) {
  1254. return p_arraydecl(tname, ispacked, confp);
  1255.     } else {
  1256. return tp_integer;
  1257.     }
  1258. }
  1259. /* VAX Pascal: */
  1260. void p_attributes()
  1261. {
  1262.     Strlist *l1;
  1263.     if (modula2)
  1264. return;
  1265.     while (curtok == TOK_LBR) {
  1266. implementationmodules = 1;    /* auto-detect VAX Pascal */
  1267. do {
  1268.     gettok();
  1269.     if (!wexpecttok(TOK_IDENT)) {
  1270. skippasttoken(TOK_RBR);
  1271. return;
  1272.     }
  1273.     l1 = strlist_append(&attrlist, strupper(curtokbuf));
  1274.     l1->value = -1;
  1275.     gettok();
  1276.     if (curtok == TOK_LPAR) {
  1277. gettok();
  1278. if (!strcmp(l1->s, "CHECK") ||
  1279.     !strcmp(l1->s, "OPTIMIZE") ||
  1280.     !strcmp(l1->s, "KEY") ||
  1281.     !strcmp(l1->s, "COMMON") ||
  1282.     !strcmp(l1->s, "PSECT") ||
  1283.     !strcmp(l1->s, "EXTERNAL") ||
  1284.     !strcmp(l1->s, "GLOBAL") ||
  1285.     !strcmp(l1->s, "WEAK_EXTERNAL") ||
  1286.     !strcmp(l1->s, "WEAK_GLOBAL")) {
  1287.     l1->value = (long)stralloc(curtokbuf);
  1288.     gettok();
  1289.     while (curtok == TOK_COMMA) {
  1290. gettok();
  1291. gettok();
  1292.     }
  1293. } else if (!strcmp(l1->s, "INHERIT") ||
  1294.    !strcmp(l1->s, "IDENT") ||
  1295.    !strcmp(l1->s, "ENVIRONMENT")) {
  1296.     p_expr(NULL);
  1297.     while (curtok == TOK_COMMA) {
  1298. gettok();
  1299. p_expr(NULL);
  1300.     }
  1301. } else {
  1302.     l1->value = ord_value(p_constant(tp_integer));
  1303.     while (curtok == TOK_COMMA) {
  1304. gettok();
  1305. p_expr(NULL);
  1306.     }
  1307. }
  1308. if (!wneedtok(TOK_RPAR)) {
  1309.     skippasttotoken(TOK_RPAR, TOK_LBR);
  1310. }
  1311.     }
  1312. } while (curtok == TOK_COMMA);
  1313. if (!wneedtok(TOK_RBR)) {
  1314.     skippasttoken(TOK_RBR);
  1315. }
  1316.     }
  1317. }
  1318. void ignore_attributes()
  1319. {
  1320.     while (attrlist) {
  1321. if (strcmp(attrlist->s, "HIDDEN") &&
  1322.     strcmp(attrlist->s, "INHERIT") &&
  1323.     strcmp(attrlist->s, "ENVIRONMENT"))
  1324.     warning(format_s("Type attribute %s ignored [128]", attrlist->s));
  1325. strlist_eat(&attrlist);
  1326.     }
  1327. }
  1328. int size_attributes()
  1329. {
  1330.     int size = -1;
  1331.     Strlist *l1;
  1332.     if ((l1 = strlist_find(attrlist, "BIT")) != NULL)
  1333. size = 1;
  1334.     else if ((l1 = strlist_find(attrlist, "BYTE")) != NULL)
  1335. size = 8;
  1336.     else if ((l1 = strlist_find(attrlist, "WORD")) != NULL)
  1337. size = 16;
  1338.     else if ((l1 = strlist_find(attrlist, "LONG")) != NULL)
  1339. size = 32;
  1340.     else if ((l1 = strlist_find(attrlist, "QUAD")) != NULL)
  1341. size = 64;
  1342.     else if ((l1 = strlist_find(attrlist, "OCTA")) != NULL)
  1343. size = 128;
  1344.     else
  1345. return -1;
  1346.     if (l1->value >= 0)
  1347. size *= l1->value;
  1348.     strlist_delete(&attrlist, l1);
  1349.     return size;
  1350. }
  1351. void p_mech_spec(doref)
  1352. int doref;
  1353. {
  1354.     if (curtok == TOK_IDENT && doref &&
  1355. !strcicmp(curtokbuf, "%REF")) {
  1356. note("Mechanism specified %REF treated like VAR [107]");
  1357. curtok = TOK_VAR;
  1358. return;
  1359.     }
  1360.     if (curtok == TOK_IDENT &&
  1361. (!strcicmp(curtokbuf, "%REF") ||
  1362.  !strcicmp(curtokbuf, "%IMMED") ||
  1363.  !strcicmp(curtokbuf, "%DESCR") ||
  1364.  !strcicmp(curtokbuf, "%STDESCR"))) {
  1365. note(format_s("Mechanism specifier %s ignored [108]", curtokbuf));
  1366. gettok();
  1367.     }
  1368. }
  1369. Type *p_modula_subrange(basetype)
  1370. Type *basetype;
  1371. {
  1372.     Type *tp;
  1373.     Value val;
  1374.     wneedtok(TOK_LBR);
  1375.     tp = maketype(TK_SUBR);
  1376.     tp->smin = p_ord_expr();
  1377.     if (basetype)
  1378. tp->smin = gentle_cast(tp->smin, basetype);
  1379.     if (wexpecttok(TOK_DOTS)) {
  1380. gettok();
  1381. tp->smax = p_ord_expr();
  1382. if (tp->smax->val.type->kind == TK_REAL &&
  1383.     tp->smax->kind == EK_CONST &&
  1384.     strlen(tp->smax->val.s) == 12 &&
  1385.     strcmp(tp->smax->val.s, "2147483648.0") >= 0 &&
  1386.     strcmp(tp->smax->val.s, "4294967295.0") <= 0) {
  1387.     tp = tp_unsigned;
  1388. } else if (basetype) {
  1389.     tp->smin = gentle_cast(tp->smin, basetype);
  1390.     tp->basetype = basetype;
  1391. } else {
  1392.     basetype = ord_type(tp->smin->val.type);
  1393.     if (basetype->kind == TK_INTEGER) {
  1394. val = eval_expr(tp->smin);
  1395. if (val.type && val.i >= 0)
  1396.     basetype = tp_unsigned;
  1397. else
  1398.     basetype = tp_integer;
  1399.     }
  1400.     tp->basetype = basetype;
  1401. }
  1402.     } else {
  1403. tp = tp_integer;
  1404.     }
  1405.     if (!wneedtok(TOK_RBR))
  1406. skippasttotoken(TOK_RBR, TOK_SEMI);
  1407.     return tp;
  1408. }
  1409. void makefakestruct(tp, tname)
  1410. Type *tp;
  1411. Meaning *tname;
  1412. {
  1413.     Symbol *sym;
  1414.     if (!tname)
  1415. return;
  1416.     while (tp && (tp->kind == TK_ARRAY || tp->kind == TK_FILE))
  1417. tp = tp->basetype;
  1418.     if (tp && tp->kind == TK_RECORD && !tp->meaning) {
  1419. sym = findsymbol(format_s(name_FAKESTRUCT, tname->name));
  1420. silentalreadydef++;
  1421. tp->meaning = addmeaning(sym, MK_TYPE);
  1422. silentalreadydef--;
  1423. tp->meaning->type = tp;
  1424. tp->meaning->refcount++;
  1425. declaretype(tp->meaning);
  1426.     }
  1427. }
  1428. Type *p_type(tname)
  1429. Meaning *tname;
  1430. {
  1431.     Type *tp;
  1432.     int ispacked = 0;
  1433.     Meaning **flast;
  1434.     Meaning *mp;
  1435.     Strlist *sl;
  1436.     int num, isfunc, saveind, savenotephase, sizespec;
  1437.     Expr *ex;
  1438.     Value val;
  1439.     static int proctypecount = 0;
  1440.     p_attributes();
  1441.     sizespec = size_attributes();
  1442.     ignore_attributes();
  1443.     tp = tp_integer;
  1444.     if (curtok == TOK_PACKED) {
  1445.         ispacked = 1;
  1446.         gettok();
  1447.     }
  1448.     checkkeyword(TOK_VARYING);
  1449.     if (modula2)
  1450. checkkeyword(TOK_POINTER);
  1451.     switch (curtok) {
  1452.         case TOK_RECORD:
  1453.             gettok();
  1454.     savenotephase = notephase;
  1455.     notephase = 1;
  1456.             tp = maketype(TK_RECORD);
  1457.             p_fieldlist(tp, &(tp->fbase), ispacked, tname);
  1458.     notephase = savenotephase;
  1459.             if (!wneedtok(TOK_END)) {
  1460. skippasttoken(TOK_END);
  1461.     }
  1462.             break;
  1463.         case TOK_ARRAY:
  1464.             gettok();
  1465.     if (!modula2) {
  1466. if (!wneedtok(TOK_LBR))
  1467.     break;
  1468.     }
  1469.     tp = p_arraydecl(tname ? tname->name : NULL, ispacked, NULL);
  1470.     makefakestruct(tp, tname);
  1471.             break;
  1472. case TOK_VARYING:
  1473.     gettok();
  1474.     tp = maketype(TK_STRING);
  1475.     if (wneedtok(TOK_LBR)) {
  1476. ex = p_ord_expr();
  1477. if (!wneedtok(TOK_RBR))
  1478.     skippasttoken(TOK_RBR);
  1479.     } else
  1480. ex = makeexpr_long(stringdefault);
  1481.     if (wneedtok(TOK_OF))
  1482. tp->basetype = p_type(NULL);
  1483.     else
  1484. tp->basetype = tp_char;
  1485.     val = eval_expr(ex);
  1486.     if (val.type) {
  1487. if (val.i > 255 && val.i > stringceiling) {
  1488.     note(format_d("Strings longer than %d may have problems [109]",
  1489.   stringceiling));
  1490. }
  1491. if (stringceiling != 255 &&
  1492.     (val.i >= 255 || val.i > stringceiling)) {
  1493.     freeexpr(ex);
  1494.     ex = makeexpr_long(stringceiling);
  1495. }
  1496.     }
  1497.     tp->indextype = makesubrangetype(tp_integer, makeexpr_long(0), ex);
  1498.     break;
  1499.         case TOK_SET:
  1500.             gettok();
  1501.             if (!wneedtok(TOK_OF))
  1502. break;
  1503.     tp = p_type(NULL);
  1504.     if (tp == tp_integer || tp == tp_unsigned)
  1505. tp = makesubrangetype(tp, makeexpr_long(0),
  1506.       makeexpr_long(defaultsetsize-1));
  1507.     if (tp->kind == TK_ENUM && !tp->meaning && useenum) {
  1508. outbasetype(tp, 0);
  1509. output(";");
  1510.     }
  1511.             tp = makesettype(tp);
  1512.             break;
  1513.         case TOK_FILE:
  1514.             gettok();
  1515.     tp = maketype(TK_FILE);
  1516.             if (curtok == TOK_OF) {
  1517.                 gettok();
  1518.                 tp->basetype = p_type(NULL);
  1519.             } else {
  1520.                 tp->basetype = tp_abyte;
  1521.             }
  1522.     if (tp->basetype->kind == TK_CHAR && charfiletext) {
  1523. tp = tp_text;
  1524.     } else {
  1525. makefakestruct(tp, tname);
  1526. tp = makepointertype(tp);
  1527.     }
  1528.             break;
  1529.         case TOK_PROCEDURE:
  1530. case TOK_FUNCTION:
  1531.     isfunc = (curtok == TOK_FUNCTION);
  1532.             gettok();
  1533.     if (curtok != TOK_LPAR && !isfunc && hasstaticlinks == 1) {
  1534. tp = tp_proc;
  1535. break;
  1536.     }
  1537.     proctypecount++;
  1538.     mp = addmeaning(findsymbol(format_d("__PROCPTR%d",
  1539. proctypecount)),
  1540.     MK_FUNCTION);
  1541.     pushctx(mp);
  1542.     tp = maketype((hasstaticlinks != 0) ? TK_PROCPTR : TK_CPROCPTR);
  1543.     tp->basetype = p_funcdecl(&isfunc, 1);
  1544.     tp->fbase = mp;   /* (saved, but not currently used) */
  1545.     tp->escale = hasstaticlinks;
  1546.     popctx();
  1547.             break;
  1548.         case TOK_HAT:
  1549. case TOK_ADDR:
  1550. case TOK_POINTER:
  1551.     if (curtok == TOK_POINTER) {
  1552. gettok();
  1553. wneedtok(TOK_TO);
  1554. if (curtok == TOK_IDENT && !strcmp(curtokbuf, "WORD")) {
  1555.     tp = tp_anyptr;
  1556.     gettok();
  1557.     break;
  1558. }
  1559.     } else
  1560. gettok();
  1561.     p_attributes();
  1562.     ignore_attributes();
  1563.             tp = maketype(TK_POINTER);
  1564.             if (curtok == TOK_IDENT &&
  1565. (!curtokmeaning || curtokmeaning->kind != MK_TYPE ||
  1566.  (deferallptrs && curtokmeaning->ctx != curctx))) {
  1567.                 struct ptrdesc *pd;
  1568.                 pd = ALLOC(1, struct ptrdesc, ptrdescs);
  1569.                 pd->sym = curtoksym;
  1570.                 pd->tp = tp;
  1571.                 pd->next = ptrbase;
  1572.                 ptrbase = pd;
  1573.                 tp->basetype = tp_abyte;
  1574. anydeferredptrs = 1;
  1575.                 gettok();
  1576.             } else {
  1577.                 tp->basetype = p_type(NULL);
  1578.                 if (!tp->basetype->pointertype)
  1579.                     tp->basetype->pointertype = tp;
  1580.             }
  1581.             break;
  1582.         case TOK_LPAR:
  1583.             if (!useenum)
  1584.                 outsection(minorspace);
  1585.     enum_tname = tname;
  1586.             tp = maketype(TK_ENUM);
  1587.             flast = &(tp->fbase);
  1588.             num = 0;
  1589.             do {
  1590.                 gettok();
  1591.                 if (!wexpecttok(TOK_IDENT)) {
  1592.     skiptotoken(TOK_RPAR);
  1593.     break;
  1594. }
  1595.                 sl = strlist_find(constmacros, curtoksym->name);
  1596.                 mp = addmeaningas(curtoksym, MK_CONST,
  1597.   (*enumformat) ? MK_VARIANT :
  1598.                                   (useenum) ? MK_VAR : MK_CONST);
  1599.                 mp->val.type = tp;
  1600.                 mp->val.i = num++;
  1601.                 mp->type = tp;
  1602.                 if (sl) {
  1603.                     mp->constdefn = (Expr *)sl->value;
  1604.                     mp->anyvarflag = 1;    /* Make sure constant is folded */
  1605.                     strlist_delete(&constmacros, sl);
  1606.                     if (mp->constdefn->kind == EK_NAME)
  1607.                         strchange(&mp->name, mp->constdefn->val.s);
  1608.                 } else {
  1609.                     if (!useenum) {
  1610. output(format_s("#define %s", mp->name));
  1611. mp->isreturn = 1;
  1612. out_spaces(constindent, 0, 0, 0);
  1613. saveind = outindent;
  1614. outindent = cur_column();
  1615. output(format_d("%dn", mp->val.i));
  1616. outindent = saveind;
  1617.     }
  1618. }
  1619.                 *flast = mp;
  1620.                 flast = &(mp->xnext);
  1621.                 gettok();
  1622.             } while (curtok == TOK_COMMA);
  1623.     if (!wneedtok(TOK_RPAR))
  1624. skippasttoken(TOK_RPAR);
  1625.             tp->smin = makeexpr_long(0);
  1626.             tp->smax = makeexpr_long(num-1);
  1627.             if (!useenum)
  1628.                 outsection(minorspace);
  1629.             break;
  1630. case TOK_LBR:
  1631.     tp = p_modula_subrange(NULL);
  1632.     break;
  1633.         case TOK_IDENT:
  1634.             if (!curtokmeaning) {
  1635.                 undefsym(curtoksym);
  1636.                 tp = tp_integer;
  1637.                 mp = addmeaning(curtoksym, MK_TYPE);
  1638.                 mp->type = tp;
  1639.                 gettok();
  1640.                 break;
  1641.             } else if (curtokmeaning == mp_string) {
  1642.                 gettok();
  1643.                 tp = maketype(TK_STRING);
  1644.                 tp->basetype = tp_char;
  1645.                 if (curtok == TOK_LBR) {
  1646.                     gettok();
  1647.                     ex = p_ord_expr();
  1648.                     if (!wneedtok(TOK_RBR))
  1649. skippasttoken(TOK_RBR);
  1650.                 } else {
  1651.     ex = makeexpr_long(stringdefault);
  1652.                 }
  1653.                 val = eval_expr(ex);
  1654.                 if (val.type && stringceiling != 255 &&
  1655.                     (val.i >= 255 || val.i > stringceiling)) {
  1656.                     freeexpr(ex);
  1657.                     ex = makeexpr_long(stringceiling);
  1658.                 }
  1659.                 tp->indextype = makesubrangetype(tp_integer, makeexpr_long(0), ex);
  1660.                 break;
  1661.             } else if (curtokmeaning->kind == MK_TYPE) {
  1662.                 tp = curtokmeaning->type;
  1663. if (sizespec > 0) {
  1664.     if (ord_type(tp)->kind == TK_INTEGER && sizespec <= 32) {
  1665. if (checkconst(tp->smin, 0)) {
  1666.     if (sizespec == 32)
  1667. tp = tp_unsigned;
  1668.     else
  1669. tp = makesubrangetype(tp_unsigned,
  1670.  makeexpr_long(0),
  1671.          makeexpr_long((1L << sizespec) - 1));
  1672. } else {
  1673.     tp = makesubrangetype(tp_integer,
  1674.      makeexpr_long(- ((1L << (sizespec-1)))),
  1675.      makeexpr_long((1L << (sizespec-1)) - 1));
  1676. }
  1677. sizespec = -1;
  1678.     }
  1679. }
  1680.                 gettok();
  1681. if (curtok == TOK_LBR) {
  1682.     if (modula2) {
  1683. tp = p_modula_subrange(tp);
  1684.     } else {
  1685. gettok();
  1686. ex = p_expr(tp_integer);
  1687. note("UCSD size spec ignored; using 'long int' [110]");
  1688. if (ord_type(tp)->kind == TK_INTEGER)
  1689.     tp = tp_integer;
  1690. if (!wneedtok(TOK_RBR))
  1691.     skippasttotoken(TOK_RBR, TOK_SEMI);
  1692.     }
  1693. }
  1694.                 break;
  1695.             }
  1696.         /* fall through */
  1697.         default:
  1698.             tp = maketype(TK_SUBR);
  1699.             tp->smin = p_ord_expr();
  1700.     if (wexpecttok(TOK_DOTS)) {
  1701. gettok();
  1702. tp->smax = p_ord_expr();
  1703. if (tp->smax->val.type->kind == TK_REAL &&
  1704.     tp->smax->kind == EK_CONST &&
  1705.     strlen(tp->smax->val.s) == 12 &&
  1706.     strcmp(tp->smax->val.s, "2147483648.0") >= 0 &&