home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 379a.lha / p2c1_13a / src / src.zoo / decl3.c < prev    next >
C/C++ Source or Header  |  1990-03-10  |  27KB  |  1,082 lines

  1. /* "p2c", a Pascal to C translator.
  2.    Copyright (C) 1989 David Gillespie.
  3.    Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation (any version).
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.  If not, write to
  16. the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  17.  
  18. #define PROTO_DECL3_C
  19. #include "trans.h"
  20.  
  21. #define MAXIMPORTS 100
  22.  
  23. extern struct ptrdesc {
  24.     struct ptrdesc *next;
  25.     Symbol *sym;
  26.     Type *tp;
  27. } *ptrbase;
  28.  
  29. extern struct ctxstack {
  30.     struct ctxstack *next;
  31.     Meaning *ctx, *ctxlast;
  32.     struct tempvarlist *tempvars;
  33.     int tempvarcount, importmark;
  34. } *ctxtop;
  35.  
  36. extern struct tempvarlist {
  37.     struct tempvarlist *next;
  38.     Meaning *tvar;
  39.     int active;
  40. } *tempvars, *stmttempvars;
  41.  
  42. extern int tempvarcount;
  43.  
  44. extern int stringtypecachesize;
  45. extern Type **stringtypecache;
  46.  
  47. extern Meaning *importlist[MAXIMPORTS];
  48. extern int firstimport;
  49.  
  50. extern Type *tp_special_anyptr;
  51.  
  52. extern int wasaliased;
  53. extern int deferallptrs;
  54. extern int anydeferredptrs;
  55. extern int silentalreadydef;
  56. extern int nonloclabelcount;
  57.  
  58. extern Strlist *varstructdecllist;
  59.  
  60. void outbasetype(type, flags)
  61. Type *type;
  62. int flags;
  63. {
  64.     Meaning *mp;
  65.     int saveindent;
  66.  
  67.     type = findbasetype(type, flags);
  68.     switch (type->kind) {
  69.  
  70.         case TK_INTEGER:
  71.             if (type == tp_uint) {
  72.                 output("unsigned");
  73.             } else if (type == tp_sint) {
  74.                 if (useAnyptrMacros == 1)
  75.                     output("Signed int");
  76.                 else if (hassignedchar)
  77.                     output("signed int");
  78.                 else
  79.                     output("int");   /* will sign-extend by hand */
  80.             } else if (type == tp_unsigned) {
  81.                 output("unsigned long");
  82.             } else if (type != tp_int)
  83.                 output(integername);
  84.             else
  85.                 output("int");
  86.             break;
  87.  
  88.         case TK_SUBR:
  89.             if (type == tp_special_anyptr) {
  90.                 output("Anyptr");
  91.             } else if (type == tp_abyte) {
  92.                 output("char");
  93.             } else if (type == tp_ubyte) {
  94.                 output(ucharname);
  95.             } else if (type == tp_sbyte) {
  96.                 output(scharname);
  97.                 if (signedchars != 1 && !hassignedchar)
  98.                     note("'signed char' may not be valid in all compilers [102]");
  99.             } else {
  100.                 if (type == tp_ushort)
  101.                     output("unsigned ");
  102.                 output("short");
  103.             }
  104.             break;
  105.  
  106.         case TK_CHAR:
  107.             if (type == tp_uchar) {
  108.                 output(ucharname);
  109.             } else if (type == tp_schar) {
  110.                 output(scharname);
  111.                 if (signedchars != 1 && !hassignedchar)
  112.                     note("'signed char' may not be valid in all compilers [102]");
  113.         } else
  114.         output(charname);
  115.             break;
  116.  
  117.         case TK_BOOLEAN:
  118.             output((*name_BOOLEAN) ? name_BOOLEAN : ucharname);
  119.             break;
  120.  
  121.         case TK_REAL:
  122.         if (type == tp_longreal)
  123.         output("double");
  124.         else
  125.         output("float");
  126.             break;
  127.  
  128.         case TK_VOID:
  129.             if (ansiC == 0)
  130.                 output("int");
  131.             else if (useAnyptrMacros == 1)
  132.                 output("Void");
  133.             else
  134.                 output("void");
  135.             break;
  136.  
  137.         case TK_PROCPTR:
  138.         output(name_PROCEDURE);
  139.         break;
  140.  
  141.         case TK_FILE:
  142.             output("FILE");
  143.             break;
  144.  
  145.     case TK_SPECIAL:
  146.         if (type == tp_jmp_buf)
  147.         output("jmp_buf");
  148.         break;
  149.  
  150.         default:
  151.             if (type->meaning && type->meaning->kind == MK_TYPE &&
  152.                 type->meaning->wasdeclared) {
  153.                 output(type->meaning->name);
  154.             } else {
  155.                 switch (type->kind) {
  156.  
  157.                     case TK_ENUM:
  158.                         output("enum {\n");
  159.             saveindent = outindent;
  160.             moreindent(tabsize);
  161.             moreindent(structindent);
  162.                         mp = type->fbase;
  163.                         while (mp) {
  164.                             output(mp->name);
  165.                             mp = mp->xnext;
  166.                             if (mp)
  167.                 output(",\001 ");
  168.                         }
  169.                         outindent = saveindent;
  170.                         output("\n}");
  171.                         break;
  172.  
  173.                     case TK_RECORD:
  174.                         if (record_is_union(type))
  175.                             output("union ");
  176.                         else
  177.                             output("struct ");
  178.                         if (type->meaning)
  179.                             output(format_s(name_STRUCT, type->meaning->name));
  180.             if (!type->structdefd) {
  181.                 if (type->meaning) {
  182.                 type->structdefd = 1;
  183.                 output(" ");
  184.                 }
  185.                             output("{\n");
  186.                 saveindent = outindent;
  187.                 moreindent(tabsize);
  188.                 moreindent(structindent);
  189.                             outfieldlist(type->fbase);
  190.                             outindent = saveindent;
  191.                             output("}");
  192.                         }
  193.             break;
  194.  
  195.             default:
  196.             break;
  197.  
  198.                 }
  199.             }
  200.             break;
  201.     }
  202. }
  203.  
  204.  
  205.  
  206. void out_type(type, witharrays)
  207. Type *type;
  208. int witharrays;
  209. {
  210.     if (!witharrays && type->kind == TK_ARRAY)
  211.         type = makepointertype(type->basetype);
  212.     outbasetype(type, 0);
  213.     outdeclarator(type, "", 0);    /* write an "abstract declarator" */
  214. }
  215.  
  216.  
  217.  
  218.  
  219. int varstorageclass(mp)
  220. Meaning *mp;
  221. {
  222.     int sclass;
  223.  
  224.     if (mp->kind == MK_PARAM || mp->kind == MK_VARPARAM ||
  225.     mp->kind == MK_FIELD)
  226.     sclass = 0;
  227.     else if (blockkind == TOK_EXPORT)
  228.         if (usevextern)
  229.         if (mp->constdefn &&
  230.         (mp->kind == MK_VAR ||
  231.          mp->kind == MK_VARREF))
  232.         sclass = 2;    /* extern */
  233.         else
  234.         sclass = 1;    /* vextern */
  235.         else
  236.             sclass = 0;                         /* (plain) */
  237.     else if (mp->isfunction && mp->kind != MK_FUNCTION)
  238.     sclass = 2;   /* extern */
  239.     else if (mp->ctx->kind == MK_MODULE &&
  240.          (var_static != 0 ||
  241.           (findsymbol(mp->name)->flags & NEEDSTATIC)) &&
  242.          !mp->exported && !mp->istemporary && blockkind != TOK_END)
  243.         sclass = (useAnyptrMacros) ? 4 : 3;     /* (private) */
  244.     else if (mp->isforward)
  245.         sclass = 3;   /* static */
  246.     else
  247.     sclass = 0;   /* (plain) */
  248.     if (mp->volatilequal)
  249.     sclass |= 0x10;
  250.     if (mp->constqual)
  251.     sclass |= 0x20;
  252.     if (debug>2) fprintf(outf, "varstorageclass(%s) = %d\n", mp->name, sclass);
  253.     return sclass;
  254. }
  255.  
  256.  
  257. char *storageclassname(i)
  258. int i;
  259. {
  260.     char *scname;
  261.  
  262.     switch (i & 0xf) {
  263.         case 1:
  264.             scname = "vextern ";
  265.         break;
  266.         case 2:
  267.             scname = "extern ";
  268.         break;
  269.         case 3:
  270.             scname = "static ";
  271.         break;
  272.         case 4:
  273.             scname = "Static ";
  274.         break;
  275.         default:
  276.             scname = "";
  277.         break;
  278.     }
  279.     if (i & 0x10)
  280.     if (useAnyptrMacros == 1)
  281.         scname = format_s("%sVolatile ", scname);
  282.     else if (ansiC > 0)
  283.         scname = format_s("%svolatile ", scname);
  284.     if (i & 0x20)
  285.     if (useAnyptrMacros == 1)
  286.         scname = format_s("%sConst ", scname);
  287.     else if (ansiC > 0)
  288.         scname = format_s("%sconst ", scname);
  289.     return scname;
  290. }
  291.  
  292.  
  293.  
  294. void declarevar(mp, which)
  295. Meaning *mp;
  296. int which;    /* 0x1=header, 0x2=body, 0x4=trailer, 0x8=in varstruct */
  297. {
  298.     int isstatic, isstructconst, saveindent;
  299.  
  300.     isstructconst = checkstructconst(mp);
  301.     isstatic = varstorageclass(mp);
  302.     if (which & 0x8)
  303.     isstatic &= 0x10;   /* clear all but Volatile flags */
  304.     flushcomments(&mp->comments, CMT_PRE, -1);
  305.     if (which & 0x1) {
  306.         if (isstructconst)
  307.             outsection(minorspace);
  308.         output(storageclassname(isstatic));
  309.         outbasetype(mp->type, 0);
  310.         output(" \005");
  311.     }
  312.     if (which & 0x2) {
  313.         outdeclarator(mp->type, mp->name, 0);
  314.         if (mp->constdefn && blockkind != TOK_EXPORT &&
  315.         (mp->kind == MK_VAR || mp->kind == MK_VARREF)) {
  316.             if (mp->varstructflag) {    /* move init code into function body */
  317.                 intwarning("declarevar",
  318.                     format_s("Variable %s initializer not removed [125]", mp->name));
  319.             } else {
  320.                 output(" = ");
  321.                 if (isstructconst) {
  322.                     output("{\n");
  323.             saveindent = outindent;
  324.             moreindent(tabsize);
  325.             moreindent(structinitindent);
  326.                     out_expr((Expr *)mp->constdefn->val.i);
  327.                     outindent = saveindent;
  328.                     output("\n}");
  329.                 } else
  330.                     out_expr(mp->constdefn);
  331.             }
  332.         }
  333.     }
  334.     if (which & 0x4) {
  335.         output(";");
  336.     outtrailcomment(mp->comments, -1, declcommentindent);
  337.     flushcomments(&mp->comments, -1, -1);
  338.         if (isstructconst)
  339.             outsection(minorspace);
  340.     }
  341. }
  342.  
  343.  
  344.  
  345.  
  346. Static int checkvarmacdef(ex, mp)
  347. Expr *ex;
  348. Meaning *mp;
  349. {
  350.     int i;
  351.  
  352.     if ((ex->kind == EK_NAME || ex->kind == EK_BICALL) &&
  353.     !strcmp(ex->val.s, mp->name)) {
  354.     ex->kind = EK_VAR;
  355.     ex->val.i = (long)mp;
  356.     ex->val.type = mp->type;
  357.     return 1;
  358.     }
  359.     if (ex->kind == EK_VAR && ex->val.i == (long)mp)
  360.     return 1;
  361.     i = ex->nargs;
  362.     while (--i >= 0)
  363.     if (checkvarmacdef(ex->args[i], mp))
  364.         return 1;
  365.     return 0;
  366. }
  367.  
  368.  
  369. int checkvarmac(mp)
  370. Meaning *mp;
  371. {
  372.     if (mp->kind != MK_VARMAC && mp->kind != MK_FUNCTION)
  373.     return 0;
  374.     if (!mp->constdefn)
  375.     return 0;
  376.     return checkvarmacdef(mp->constdefn, mp);
  377. }
  378.  
  379.  
  380.  
  381. #define varkind(k) ((k)==MK_VAR||(k)==MK_VARREF||(k)==MK_PARAM||(k)==MK_VARPARAM)
  382.  
  383. int declarevars(ctx, invarstruct)
  384. Meaning *ctx;
  385. int invarstruct;
  386. {
  387.     Meaning *mp, *mp0, *mp2;
  388.     Strlist *fnames, *fn;
  389.     int flag, first;
  390.  
  391.     if (ctx->kind == MK_FUNCTION && ctx->varstructflag && !invarstruct) {
  392.         output("struct ");
  393.         output(format_s(name_LOC, ctx->name));
  394.         output(" ");
  395.         output(format_s(name_VARS, ctx->name));
  396.         output(";\n");
  397.         flag = 1;
  398.     } else
  399.         flag = 0;
  400.     if (debug>2) {
  401.         fprintf(outf,"declarevars:\n");
  402.         for (mp = ctx->cbase; mp; mp = mp->xnext) {
  403.             fprintf(outf, "  %-22s%-15s%3d", mp->name,
  404.                                              meaningkindname(mp->kind),
  405.                                              mp->refcount);
  406.             if (mp->wasdeclared)
  407.                 fprintf(outf, " [decl]");
  408.             if (mp->varstructflag)
  409.                 fprintf(outf, " [struct]");
  410.             fprintf(outf, "\n");
  411.         }
  412.     }
  413.     fnames = NULL;
  414.     for (;;) {
  415.         mp = ctx->cbase;
  416.         while (mp && (!(varkind(mp->kind) || checkvarmac(mp)) ||
  417.               mp->wasdeclared || mp->varstructflag != invarstruct ||
  418.               mp->refcount <= 0))
  419.             mp = mp->cnext;
  420.         if (!mp)
  421.             break;
  422.         flag = 1;
  423.         first = 1;
  424.         mp0 = mp2 = mp;
  425.         while (mp) {
  426.             if ((varkind(mp->kind) || checkvarmac(mp)) &&
  427.         !mp->wasdeclared &&
  428.                 varstorageclass(mp) == varstorageclass(mp0) &&
  429.                 mp->varstructflag == invarstruct && mp->refcount > 0) {
  430.                 if (mixable(mp2, mp, 0, 0) || first) {
  431.                     if (!first)
  432.                         output(",\001 ");
  433.                     declarevar(mp, (first ? 0x3 : 0x2) |
  434.                        (invarstruct ? 0x8 : 0));
  435.             mp2 = mp;
  436.                     mp->wasdeclared = 1;
  437.                     if (isfiletype(mp->type)) {
  438.                         fn = strlist_append(&fnames, mp->name);
  439.                         fn->value = (long)mp;
  440.                     }
  441.                     first = 0;
  442.                 } else
  443.                     if (mixvars != 1)
  444.                         break;
  445.             }
  446.         if (first) {
  447.         intwarning("declarevars",
  448.                format_s("Unable to declare %s [126]", mp->name));
  449.         mp->wasdeclared = 1;
  450.         first = 0;
  451.         }
  452.             if (mixvars == 0)
  453.                 break;
  454.             mp = mp->cnext;
  455.         }
  456.         declarevar(mp2, 0x4);
  457.     }
  458.     declarefiles(fnames);
  459.     return flag;
  460. }
  461.  
  462.  
  463.  
  464. void redeclarevars(ctx)
  465. Meaning *ctx;
  466. {
  467.     Meaning *mp;
  468.  
  469.     for (mp = ctx->cbase; mp; mp = mp->cnext) {
  470.         if ((mp->kind == MK_VAR || mp->kind == MK_VARREF) &&
  471.             mp->constdefn) {
  472.             mp->wasdeclared = 0;    /* mark for redeclaration, this time */
  473.         }                           /*  with its initializer */
  474.     }
  475. }
  476.  
  477.  
  478.  
  479.  
  480.  
  481. void out_argdecls(ftype)
  482. Type *ftype;
  483. {
  484.     Meaning *mp, *mp0;
  485.     Type *tp;
  486.     int done;
  487.     int flag = 1;
  488.     char *name;
  489.  
  490.     done = 0;
  491.     do {
  492.         mp = ftype->fbase;
  493.         while (mp && mp->wasdeclared)
  494.             mp = mp->xnext;
  495.         if (mp) {
  496.             if (flag)
  497.                 output("\n");
  498.             flag = 0;
  499.             mp0 = mp;
  500.             outbasetype(mp->othername ? mp->rectype : mp->type,
  501.             ODECL_CHARSTAR|ODECL_FREEARRAY);
  502.             output(" \005");
  503.             while (mp) {
  504.                 if (!mp->wasdeclared) {
  505.                     if (mp == mp0 ||
  506.             mixable(mp0, mp, 1, ODECL_CHARSTAR|ODECL_FREEARRAY)) {
  507.                         if (mp != mp0)
  508.                             output(",\001 ");
  509.                         name = (mp->othername) ? mp->othername : mp->name;
  510.                         tp = (mp->othername) ? mp->rectype : mp->type;
  511.                         outdeclarator(tp, name,
  512.                       ODECL_CHARSTAR|ODECL_FREEARRAY);
  513.                         mp->wasdeclared = 1;
  514.                     } else
  515.                         if (mixvars != 1)
  516.                             break;
  517.                 }
  518.                 mp = mp->xnext;
  519.             }
  520.             output(";\n");
  521.         } else
  522.             done = 1;
  523.     } while (!done);
  524.     for (mp0 = ftype->fbase; mp0 && (mp0->type != tp_strptr ||
  525.                                      !mp0->anyvarflag); mp0 = mp0->xnext) ;
  526.     if (mp0) {
  527.         output("int ");
  528.         for (mp = mp0; mp; mp = mp->xnext) {
  529.             if (mp->type == tp_strptr && mp->anyvarflag) {
  530.                 if (mp != mp0) {
  531.                     if (mixvars == 0)
  532.                         output(";\nint ");
  533.                     else
  534.                         output(",\001 ");
  535.                 }
  536.                 output(format_s(name_STRMAX, mp->name));
  537.             }
  538.         }
  539.         output(";\n");
  540.     }
  541.     if (ftype->meaning && ftype->meaning->ctx->kind == MK_FUNCTION &&
  542.                           ftype->meaning->ctx->varstructflag) {
  543.         if (flag)
  544.             output("\n");
  545.         output("struct ");
  546.         output(format_s(name_LOC, ftype->meaning->ctx->name));
  547.         output(" *");
  548.         output(format_s(name_LINK, ftype->meaning->ctx->name));
  549.         output(";\n");
  550.     }
  551. }
  552.  
  553.  
  554.  
  555.  
  556. void makevarstruct(func)
  557. Meaning *func;
  558. {
  559.     int flag = 0;
  560.     int saveindent;
  561.  
  562.     outsection(minfuncspace);
  563.     output(format_s("\n/* Local variables for %s: */\n", func->name));
  564.     output("struct ");
  565.     output(format_s(name_LOC, func->name));
  566.     output(" {\n");
  567.     saveindent = outindent;
  568.     moreindent(tabsize);
  569.     moreindent(structindent);
  570.     if (func->ctx->kind == MK_FUNCTION && func->ctx->varstructflag) {
  571.         output("struct ");
  572.         output(format_s(name_LOC, func->ctx->name));
  573.         output(" *");
  574.         output(format_s(name_LINK, func->ctx->name));
  575.         output(";\n");
  576.         flag++;
  577.     }
  578.     flag += declarevars(func, 1);
  579.     if (!flag)                       /* Avoid generating an empty struct */
  580.         output("int _meef_;\n");     /* (I don't think this will ever happen) */
  581.     outindent = saveindent;
  582.     output("} ;\n");
  583.     outsection(minfuncspace);
  584.     strlist_insert(&varstructdecllist, func->name);
  585. }
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592. Type *maketype(kind)
  593. enum typekind kind;
  594. {
  595.     Type *tp;
  596.     tp = ALLOC(1, Type, types);
  597.     tp->kind = kind;
  598.     tp->basetype = NULL;
  599.     tp->indextype = NULL;
  600.     tp->pointertype = NULL;
  601.     tp->meaning = NULL;
  602.     tp->fbase = NULL;
  603.     tp->smin = NULL;
  604.     tp->smax = NULL;
  605.     tp->issigned = 0;
  606.     tp->dumped = 0;
  607.     tp->structdefd = 0;
  608.     return tp;
  609. }
  610.  
  611.  
  612.  
  613.  
  614. Type *makesubrangetype(type, smin, smax)
  615. Type *type;
  616. Expr *smin, *smax;
  617. {
  618.     Type *tp;
  619.  
  620.     if (type->kind == TK_SUBR)
  621.         type = type->basetype;
  622.     tp = maketype(TK_SUBR);
  623.     tp->basetype = type;
  624.     tp->smin = smin;
  625.     tp->smax = smax;
  626.     return tp;
  627. }
  628.  
  629.  
  630.  
  631. Type *makesettype(setof)
  632. Type *setof;
  633. {
  634.     Type *tp;
  635.     long smax;
  636.  
  637.     if (ord_range(setof, NULL, &smax) && smax < setbits && smallsetconst >= 0)
  638.         tp = maketype(TK_SMALLSET);
  639.     else
  640.         tp = maketype(TK_SET);
  641.     tp->basetype = tp_integer;
  642.     tp->indextype = setof;
  643.     return tp;
  644. }
  645.  
  646.  
  647.  
  648. Type *makestringtype(len)
  649. int len;
  650. {
  651.     Type *type;
  652.     int index;
  653.  
  654.     len |= 1;
  655.     if (len >= stringceiling)
  656.         type = tp_str255;
  657.     else {
  658.         index = (len-1) / 2;
  659.         if (stringtypecache[index])
  660.             return stringtypecache[index];
  661.         type = maketype(TK_STRING);
  662.         type->basetype = tp_char;
  663.         type->indextype = makesubrangetype(tp_integer, 
  664.                                            makeexpr_long(0), 
  665.                                            makeexpr_long(len));
  666.         stringtypecache[index] = type;
  667.     }
  668.     return type;
  669. }
  670.  
  671.  
  672.  
  673. Type *makepointertype(type)
  674. Type *type;
  675. {
  676.     Type *tp;
  677.  
  678.     if (type->pointertype)
  679.         return type->pointertype;
  680.     tp = maketype(TK_POINTER);
  681.     tp->basetype = type;
  682.     type->pointertype = tp;
  683.     return tp;
  684. }
  685.  
  686.  
  687.  
  688.  
  689.  
  690. Value p_constant(type)
  691. Type *type;
  692. {
  693.     Value val;
  694.     Expr *ex;
  695.  
  696.     ex = p_expr(type);
  697.     if (type)
  698.         ex = gentle_cast(ex, type);
  699.     val = eval_expr(ex);
  700.     freeexpr(ex);
  701.     if (!val.type) {
  702.         warning("Expected a constant [127]");
  703.         val.type = (type) ? type : tp_integer;
  704.     }
  705.     return val;
  706. }
  707.  
  708.  
  709.  
  710.  
  711. int typebits(smin, smax)
  712. long smin, smax;
  713. {
  714.     unsigned long size;
  715.     int bits;
  716.  
  717.     if (smin >= 0 || (smin == -1 && smax == 0)) {
  718.         bits = 1;
  719.         size = smax;
  720.     } else {
  721.         bits = 2;
  722.         smin = -1L - smin;
  723.         if (smin >= smax)
  724.             size = smin;
  725.         else
  726.             size = smax;
  727.     }
  728.     while (size > 1) {
  729.         bits++;
  730.         size >>= 1;
  731.     }
  732.     return bits;
  733. }
  734.  
  735.  
  736. int packedsize(fname, typep, sizep, mode)
  737. char *fname;
  738. Type **typep;
  739. long *sizep;
  740. int mode;
  741. {
  742.     Type *tp = *typep;
  743.     long smin, smax;
  744.     int res, issigned;
  745.     short savefold;
  746.     long size;
  747.  
  748.     if (packing == 0)   /* suppress packing */
  749.         return 0;
  750.     if (tp->kind != TK_SUBR && tp->kind != TK_INTEGER && tp->kind != TK_ENUM &&
  751.         tp->kind != TK_CHAR && tp->kind != TK_BOOLEAN)
  752.         return 0;
  753.     if (tp == tp_unsigned)
  754.     return 0;
  755.     if (!ord_range(tp, &smin, &smax)) {
  756.         savefold = foldconsts;
  757.         foldconsts = 1;
  758.         res = ord_range(tp, &smin, &smax);
  759.         foldconsts = savefold;
  760.         if (res) {
  761.             note(format_s("Field width for %s is based on expansion of #defines [103]",
  762.                           fname));
  763.         } else {
  764.             note(format_ss("Cannot compute size of field %s; assuming %s [104]",
  765.                            fname, integername));
  766.             return 0;
  767.         }
  768.     } else {
  769.         if (tp->kind == TK_ENUM)
  770.             note(format_ssd("Field width for %s assumes enum%s has %d elements [105]",
  771.                             fname,
  772.                             (tp->meaning) ? format_s(" %s", tp->meaning->name) : "",
  773.                             smax + 1));
  774.     }
  775.     issigned = (smin < 0);
  776.     size = typebits(smin, smax);
  777.     if (size >= ((sizeof_long > 0) ? sizeof_long : 32))
  778.         return 0;
  779.     if (packing != 1) {
  780.         if (size <= 8)
  781.             size = 8;
  782.         else if (size <= 16)
  783.             size = 16;
  784.         else
  785.             return 0;
  786.     }
  787.     if (!issigned) {
  788.         *typep = (mode == 0) ? tp_int : tp_uint;
  789.     } else {
  790.         if (mode == 2 && !hassignedchar && !*signextname)
  791.             return 0;
  792.         *typep = (mode == 1) ? tp_int : tp_sint;
  793.     }
  794.     *sizep = size;
  795.     return issigned;
  796. }
  797.  
  798.  
  799.  
  800. Static void fielddecl(mp, type, tp2, val, ispacked, aligned)
  801. Meaning *mp;
  802. Type **type, **tp2;
  803. long *val;
  804. int ispacked, *aligned;
  805. {
  806.     long smin, smax, smin2, smax2;
  807.  
  808.     *tp2 = *type;
  809.     *val = 0;
  810.     if (ispacked && !mp->constdefn && *type != tp_unsigned) {
  811.         (void)packedsize(mp->sym->name, tp2, val, signedfield);
  812.         if (*aligned && *val &&
  813.             (ord_type(*type)->kind == TK_CHAR ||
  814.              ord_type(*type)->kind == TK_INTEGER) &&
  815.             ord_range(findbasetype(*type, 0), &smin, &smax)) {
  816.         if (ord_range(*type, &smin2, &smax2)) {
  817.         if (typebits(smin, smax) == 16 &&
  818.             typebits(smin2, smax2) == 8 && *val == 8) {
  819.             *tp2 = tp_abyte;
  820.         }
  821.         }
  822.         if (typebits(smin, smax) == *val &&
  823.         *val != 7) {    /* don't be fooled by tp_abyte */
  824.         /* don't need to use a bit-field for this field */
  825.         /* so not specifying one may make it more efficient */
  826.         /* (and also helps to simulate HP's $allow_packed$ mode) */
  827.         *val = 0;
  828.         *tp2 = *type;
  829.         } 
  830.         }
  831.         if (*aligned && *val == 8 &&
  832.             (ord_type(*type)->kind == TK_BOOLEAN ||
  833.              ord_type(*type)->kind == TK_ENUM)) {
  834.             *val = 0;
  835.             *tp2 = tp_ubyte;
  836.         }
  837.     }
  838.     if (*val != 8 && *val != 16)
  839.     *aligned = (*val == 0);
  840. }
  841.  
  842.  
  843.  
  844. /* This function locates byte-sized fields which were unaligned, but which
  845.    are followed by aligned quantities so that they can be made aligned
  846.    with no loss in storage efficiency. */
  847.  
  848. Static void realignfields(firstmp, stopmp)
  849. Meaning *firstmp, *stopmp;
  850. {
  851.     Meaning *mp;
  852.  
  853.     for (mp = firstmp; mp && mp != stopmp; mp = mp->cnext) {
  854.     if (mp->kind == MK_FIELD) {
  855.         if (mp->val.i == 16) {
  856.         if (mp->type == tp_uint)
  857.             mp->type = tp_ushort;
  858.         else
  859.             mp->type = tp_sshort;
  860.         mp->val.i = 0;
  861.         } else if (mp->val.i == 8) {
  862.         if (mp->type == tp_uint) {
  863.             mp->type = tp_ubyte;
  864.             mp->val.i = 0;
  865.         } else if (hassignedchar || signedchars == 1) {
  866.             mp->type = tp_sbyte;
  867.             mp->val.i = 0;
  868.         } else
  869.             mp->type = tp_abyte;
  870.         }
  871.     }
  872.     }
  873. }
  874.  
  875. static void tryrealignfields(firstmp)
  876. Meaning *firstmp;
  877. {
  878.     Meaning *mp, *head;
  879.  
  880.     head = NULL;
  881.     for (mp = firstmp; mp; mp = mp->cnext) {
  882.     if (mp->kind == MK_FIELD) {
  883.         if (mp->val.i == 8 || mp->val.i == 16) {
  884.         if (!head)
  885.             head = mp;
  886.         } else {
  887.         if (mp->val.i == 0)
  888.             realignfields(head, mp);
  889.         head = NULL;
  890.         }
  891.     }
  892.     }
  893.     realignfields(head, NULL);
  894. }
  895.  
  896.  
  897.  
  898. void decl_comments(mp)
  899. Meaning *mp;
  900. {
  901.     Strlist *cmt;
  902.  
  903.     if (spitcomments != 1) {
  904.     changecomments(curcomments, -1, -1, CMT_PRE, 0);
  905.     strlist_mix(&mp->comments, curcomments);
  906.     curcomments = NULL;
  907.     cmt = grabcomment(CMT_TRAIL);
  908.     if (cmt) {
  909.         changecomments(mp->comments, CMT_TRAIL, -1, CMT_PRE, -1);
  910.         strlist_mix(&mp->comments, cmt);
  911.     }
  912.     if (mp->comments)
  913.         mp->refcount++;   /* force it to be included if it has comments */
  914.     }
  915. }
  916.  
  917.  
  918.  
  919.  
  920.  
  921. Static void p_fieldlist(tp, flast, ispacked, tname)
  922. Type *tp;
  923. Meaning **flast;
  924. int ispacked;
  925. Meaning *tname;
  926. {
  927.     Meaning *firstm, *lastm, *veryfirstm;
  928.     Symbol *sym;
  929.     Type *type, *tp2;
  930.     long li1, li2;
  931.     int aligned, constflag, volatileflag;
  932.     short saveskipind;
  933.     Strlist *l1;
  934.  
  935.     saveskipind = skipindices;
  936.     skipindices = 0;
  937.     aligned = 1;
  938.     lastm = NULL;
  939.     veryfirstm = NULL;
  940.     while (curtok == TOK_IDENT) {
  941.         firstm = addfield(curtoksym, &flast, tp, tname);
  942.     if (!veryfirstm)
  943.         veryfirstm = firstm;
  944.         lastm = firstm;
  945.         gettok();
  946.     decl_comments(lastm);
  947.         while (curtok == TOK_COMMA) {
  948.             gettok();
  949.             if (wexpecttok(TOK_IDENT))
  950.         lastm = addfield(curtoksym, &flast, tp, tname);
  951.             gettok();
  952.         decl_comments(lastm);
  953.         }
  954.         if (wneedtok(TOK_COLON)) {
  955.         constflag = volatileflag = 0;
  956.         p_attributes();
  957.         if ((l1 = strlist_find(attrlist, "READONLY")) != NULL) {
  958.         constflag = 1;
  959.         strlist_delete(&attrlist, l1);
  960.         }
  961.         if ((l1 = strlist_find(attrlist, "VOLATILE")) != NULL) {
  962.         volatileflag = 1;
  963.         strlist_delete(&attrlist, l1);
  964.         }
  965.         type = p_type(firstm);
  966.         decl_comments(lastm);
  967.         fielddecl(firstm, &type, &tp2, &li1, ispacked, &aligned);
  968.         for (;;) {
  969.         firstm->type = tp2;
  970.         firstm->val.type = type;
  971.         firstm->val.i = li1;
  972.         firstm->constqual = constflag;
  973.         firstm->volatilequal = volatileflag;
  974.         tp->meaning = tname;
  975.         setupfilevar(firstm);
  976.         tp->meaning = NULL;
  977.         if (firstm == lastm)
  978.             break;
  979.         firstm = firstm->cnext;
  980.         }
  981.     } else
  982.         skiptotoken2(TOK_SEMI, TOK_CASE);
  983.         if (curtok == TOK_SEMI)
  984.             gettok();
  985.     }
  986.     if (curtok == TOK_CASE) {
  987.         gettok();
  988.     if (curtok == TOK_COLON)
  989.         gettok();
  990.     wexpecttok(TOK_IDENT);
  991.     sym = curtoksym;
  992.     if (curtokmeaning)
  993.         type = curtokmeaning->type;
  994.     gettok();
  995.         if (curtok == TOK_COLON) {
  996.             firstm = addfield(sym, &flast, tp, tname);
  997.         if (!veryfirstm)
  998.         veryfirstm = firstm;
  999.             gettok();
  1000.         firstm->isforward = 1;
  1001.             firstm->val.type = type = p_type(firstm);
  1002.             fielddecl(firstm, &firstm->val.type, &firstm->type, &firstm->val.i, 
  1003.                       ispacked, &aligned);
  1004.         } else {
  1005.         firstm = NULL;
  1006.     }
  1007.         if (!wneedtok(TOK_OF)) {
  1008.         skiptotoken2(TOK_END, TOK_RPAR);
  1009.         goto bounce;
  1010.     }
  1011.     if (firstm)
  1012.         decl_comments(firstm);
  1013.     while (curtok == TOK_VBAR)
  1014.         gettok();
  1015.         while (curtok != TOK_END && curtok != TOK_RPAR) {
  1016.             firstm = NULL;
  1017.             for (;;) {
  1018.         lastm = addfield(NULL, &flast, tp, tname);
  1019.         if (!firstm)
  1020.             firstm = lastm;
  1021.         checkkeyword(TOK_OTHERWISE);
  1022.         if (curtok == TOK_ELSE || curtok == TOK_OTHERWISE) {
  1023.             lastm->val = make_ord(type, 999);
  1024.             break;
  1025.         } else {
  1026.             lastm->val = p_constant(type);
  1027.             if (curtok == TOK_DOTS) {
  1028.             gettok();
  1029.             li1 = ord_value(lastm->val);
  1030.             li2 = ord_value(p_constant(type));
  1031.             while (++li1 <= li2) {
  1032.                 lastm = addfield(NULL, &flast, tp, tname);
  1033.                 lastm->val = make_ord(type, li1);
  1034.             }
  1035.             }
  1036.         }
  1037.                 if (curtok == TOK_COMMA)
  1038.                     gettok();
  1039.                 else
  1040.                     break;
  1041.             }
  1042.         if (curtok == TOK_ELSE || curtok == TOK_OTHERWISE) {
  1043.         gettok();
  1044.             } else if (!wneedtok(TOK_COLON) ||
  1045.              (!modula2 && !wneedtok(TOK_LPAR))) {
  1046.         skiptotoken2(TOK_END, TOK_RPAR);
  1047.         goto bounce;
  1048.         }
  1049.             p_fieldlist(tp, &lastm->ctx, ispacked, tname);
  1050.             while (firstm != lastm) {
  1051.                 firstm->ctx = lastm->ctx;
  1052.                 firstm = firstm->cnext;
  1053.             }
  1054.         if (modula2) {
  1055.         while (curtok == TOK_VBAR)
  1056.             gettok();
  1057.         } else {
  1058.         if (!wneedtok(TOK_RPAR))
  1059.             skiptotoken(TOK_RPAR);
  1060.         }
  1061.             if (curtok == TOK_SEMI)
  1062.                 gettok();
  1063.         }
  1064.     if (modula2) {
  1065.         wneedtok(TOK_END);
  1066.         if (curtok == TOK_IDENT) {
  1067.         note("Record variants supported only at end of record [106]");
  1068.         p_fieldlist(tp, &lastm->ctx, ispacked, tname);
  1069.         }
  1070.     }
  1071.     }
  1072.     tryrealignfields(veryfirstm);
  1073.     if (lastm && curtok == TOK_END) {
  1074.     strlist_mix(&lastm->comments, curcomments);
  1075.     curcomments = NULL;
  1076.     }
  1077.  
  1078.   bounce:
  1079.     skipindices = saveskipind;
  1080. }
  1081.  
  1082.