Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "tok.h"
  2.  
  3.  
  4.  
  5. void  obj_outrecord(int recordtype,unsigned int recordlength,unsigned char *data);
  6.  
  7. void outeachPUBDEF(struct idrec *ptr);
  8.  
  9. void  obj_outLEDATA(unsigned int segm,unsigned int offset,unsigned int recordlength,
  10.  
  11.                          unsigned char *data);
  12.  
  13.  
  14.  
  15. #define MAXNUMEXTNAME 1024;
  16.  
  17.  
  18.  
  19. int *numextname;
  20.  
  21. int maxnumextname=MAXNUMEXTNAME;
  22.  
  23. unsigned int lenextstr=0;       //¤«¨­  áâப¨ á ¢­¥è­¨¬¨ ¨¬¥­ ¬¨
  24.  
  25. int numextern=0;
  26.  
  27.  
  28.  
  29. int postseg,stackseg;
  30.  
  31.  
  32.  
  33. unsigned int findextname(int extnum)
  34.  
  35. {
  36.  
  37.         for(unsigned int i=0;i<externnum;i++){
  38.  
  39.                 if(numextname[i]==extnum)return i+1;
  40.  
  41.         }
  42.  
  43.         return 0;
  44.  
  45. }
  46.  
  47.  
  48.  
  49. int MakeObj()
  50.  
  51. {
  52.  
  53. unsigned int i;
  54.  
  55. unsigned int count,sizeblock;
  56.  
  57.         hout=CreateOutPut("obj","wb");
  58.  
  59.         i=strlen(startfileinfo->filename);
  60.  
  61.         string2[0]=(unsigned char)i;
  62.  
  63.         strcpy((char *)&string2[1],startfileinfo->filename);
  64.  
  65.         obj_outrecord(0x80,i+1,&string2[0]);// output the LNAMES
  66.  
  67.         sprintf((char *)&string2[3],"%s %s",compilerstr,__DATE__);
  68.  
  69.         i=strlen((char *)&string2[3]);
  70.  
  71.         *(short *)&string2[0]=0;
  72.  
  73.         string2[2]=(unsigned char)i;
  74.  
  75.         obj_outrecord(0x88,i+3,&string2[0]);// output the LNAMES
  76.  
  77.         for(count=0;count<totalmodule;count++){ //¨¬¥­  ¢ª«îç ¥¬ëå ä ©«®¢
  78.  
  79.                 *(struct ftime *)&string2[2]=(startfileinfo+count)->time;
  80.  
  81.                 strcpy((char *)&string2[7],(startfileinfo+count)->filename);
  82.  
  83.                 i=strlen((startfileinfo+count)->filename);
  84.  
  85.                 *(short *)&string2[0]=0xE940;
  86.  
  87.                 string2[6]=(unsigned char)i;
  88.  
  89.                 obj_outrecord(0x88,i+7,&string2[0]);// output the LNAMES
  90.  
  91.         }
  92.  
  93.         count=outptr-startptr;  //à §¬¥à ª®¤ 
  94.  
  95.         unsigned char *data=output+startptr;    //­ ç «® ¤ ­­ëå
  96.  
  97.         *(short *)&string2[0]=0xE940;
  98.  
  99.         obj_outrecord(0x88,2,&string2[0]);//ª®­¥æ ª®¬¥­â à¨©
  100.  
  101.         if(!am32){
  102.  
  103.                 *(short *)&string2[0]=0xEA00;
  104.  
  105.                 string2[2]=1;
  106.  
  107.                 string2[3]=(unsigned char)(modelmem==SMALL?9:8);
  108.  
  109.                 obj_outrecord(0x88,4,&string2[0]);
  110.  
  111.         }
  112.  
  113.         else{
  114.  
  115.                 *(short *)&string2[0]=0xA140;
  116.  
  117.                 obj_outrecord(0x88,2,&string2[0]);
  118.  
  119.         }
  120.  
  121.         obj_outrecord(0x96,39,(unsigned char *)"\000\005_TEXT\004CODE\004_BSS\003BSS\006DGROUP\005_DATA\004DATA");
  122.  
  123. // output the SEGDEF
  124.  
  125.         if(!am32){
  126.  
  127.                 string2[0]=(unsigned char)0x28;
  128.  
  129.                 *(short *)&string2[1]=(short)outptr;//count;// Set the length of the segment of DATA or CODE
  130.  
  131.                 string2[3]=0x02;        //¨¬ï ᥣ¬¥­â  _TEXT
  132.  
  133.                 *(short *)&string2[4]=0x0103;   //ª« áá CODE Overlay NONE 1
  134.  
  135.                 obj_outrecord(0x98,6,string2);
  136.  
  137.                 i=2;
  138.  
  139.  
  140.  
  141.                 if(comfile==file_exe&&modelmem==SMALL){
  142.  
  143.                         string2[0]=(unsigned char)0x48;
  144.  
  145.                         *(short *)&string2[1]=outptrdata;// Set the length of the segment DATA
  146.  
  147.                         string2[3]=0x07;        //¨¬ï ᥣ¬¥­â  _DATA
  148.  
  149.                         *(short *)&string2[4]=0x0108;   //ª« áá DATA Overlay NONE
  150.  
  151.                         obj_outrecord(0x98,6,string2);
  152.  
  153.                         i++;
  154.  
  155.                 }
  156.  
  157.  
  158.  
  159.                 postseg=i;
  160.  
  161.                 string2[0]=(unsigned char)0x48;
  162.  
  163.                 *(short *)&string2[1]=(short)postsize;// Set the length of the segment BSS
  164.  
  165.                 string2[3]=0x04;        //¨¬ï ᥣ¬¥­â  _BSS
  166.  
  167.                 *(short *)&string2[4]=0x0105;   //ª« áá BSS Overlay NONE
  168.  
  169.                 obj_outrecord(0x98,6,string2);
  170.  
  171.                 i++;
  172.  
  173.  
  174.  
  175.                 if(comfile==file_exe&&modelmem==SMALL){
  176.  
  177.                         obj_outrecord(0x96,6,(unsigned char *)"\005STACK");
  178.  
  179.                         string2[0]=0x74;
  180.  
  181.                         *(short *)&string2[1]=(short)stacksize;// Set the length of the segment STACK
  182.  
  183.                         string2[3]=0x09;        //¨¬ï ᥣ¬¥­â  STACK
  184.  
  185.                         *(short *)&string2[4]=0x0109;   //ª« áá STACK Overlay NONE
  186.  
  187.                         obj_outrecord(0x98,6,string2);
  188.  
  189.                         stackseg=i;
  190.  
  191.                 }
  192.  
  193.                 string2[0]=6;   //¨¬ï DGROUP
  194.  
  195.                 if(comfile==file_exe&&modelmem==SMALL){
  196.  
  197.                         *(short *)&string2[1]=0x2FF;
  198.  
  199.                         *(short *)&string2[3]=0x3FF;//postseg*256+255;//0x3FF;
  200.  
  201.                         *(short *)&string2[5]=0x4ff;//stackseg*256+255;//0x4FF;
  202.  
  203.                         i=7;
  204.  
  205.                 }
  206.  
  207.                 else{
  208.  
  209.                         *(short *)&string2[1]=0x1FF;
  210.  
  211. //                      *(short *)&string2[3]=0x2FF;
  212.  
  213.                         *(short *)&string2[3]=0x2ff;//postseg*256+255;//0x3FF;
  214.  
  215.                         i=5;
  216.  
  217.                 }
  218.  
  219.                 obj_outrecord(0x9A,i,string2);
  220.  
  221.         }
  222.  
  223.         else{
  224.  
  225.                 string2[0]=(unsigned char)0xA9;
  226.  
  227.                 *(long *)&string2[1]=(long)outptr;//count;// Set the length of the segment of DATA or CODE
  228.  
  229.                 string2[5]=0x02;        //¨¬ï ᥣ¬¥­â  _TEXT
  230.  
  231.                 *(short *)&string2[6]=0x0103;   //ª« áá CODE Overlay NONE
  232.  
  233.                 obj_outrecord(0x99,8,string2);
  234.  
  235.                 i=2;
  236.  
  237. /*
  238.  
  239.                 string2[0]=(unsigned char)0xA9;
  240.  
  241.                 *(long *)&string2[1]=0;// Set the length of the segment DATA
  242.  
  243.                 string2[5]=0x07;        //¨¬ï ᥣ¬¥­â  _DATA
  244.  
  245.                 *(short *)&string2[6]=0x0108;   //ª« áá DATA Overlay NONE
  246.  
  247.                 obj_outrecord(0x99,8,string2);
  248.  
  249.                 i++;*/
  250.  
  251.  
  252.  
  253.                 postseg=i;
  254.  
  255.                 string2[0]=(unsigned char)0xA9;
  256.  
  257.                 *(long *)&string2[1]=(long)postsize;// Set the length of the segment BSS
  258.  
  259.                 string2[5]=0x04;        //¨¬ï ᥣ¬¥­â  _BSS
  260.  
  261.                 *(short *)&string2[6]=0x0105;   //ª« áá BSS Overlay NONE
  262.  
  263.                 obj_outrecord(0x99,8,string2);
  264.  
  265.                 i++;
  266.  
  267.  
  268.  
  269.                 obj_outrecord(0x96,11,(unsigned char *)"\005STACK\004FLAT");//9,10
  270.  
  271.  
  272.  
  273.                 if(comfile!=file_w32){
  274.  
  275.                         string2[0]=0x75;
  276.  
  277.                         *(long *)&string2[1]=(long)stacksize;// Set the length of the segment STACK
  278.  
  279.                         string2[5]=0x09;        //¨¬ï ᥣ¬¥­â  STACK
  280.  
  281.                         *(short *)&string2[6]=0x0109;   //ª« áá STACK Overlay NONE
  282.  
  283.                         obj_outrecord(0x99,8,string2);
  284.  
  285.                         stackseg=i;
  286.  
  287.                 }
  288.  
  289.                 string2[0]=10;
  290.  
  291.  
  292.  
  293.                 obj_outrecord(0x9A,1,string2);  //GRPDEF Group: FLAT
  294.  
  295.                 string2[0]=6;   //¨¬ï DGROUP
  296.  
  297.                 i=1;
  298.  
  299. //              *(short *)&string2[i]=0x2FF;    //DATA
  300.  
  301. //              i+=2;
  302.  
  303.                 *(short *)&string2[i]=postseg*256+255;//0x3FF;  //BSS
  304.  
  305.                 i+=2;
  306.  
  307.                 if(comfile!=file_w32){
  308.  
  309.                         *(short *)&string2[i]=stackseg*256+255;//0x4FF
  310.  
  311.                         i+=2;
  312.  
  313.                 }
  314.  
  315.                 obj_outrecord(0x9A,i,string2);
  316.  
  317.         }
  318.  
  319. // ¢ë¢®¤ EXTDEF
  320.  
  321.         while(externnum>maxnumextname)maxnumextname+=MAXNUMEXTNAME;
  322.  
  323.         numextname=(int *)MALLOC(maxnumextname*sizeof(int));
  324.  
  325. // output the PUBDEF records for each exteral procedures (all procedures)
  326.  
  327.         outeachPUBDEF(treestart);
  328.  
  329.         if(lenextstr!=0)obj_outrecord(0x8c,lenextstr,&string[0]);
  330.  
  331. // output the data (LEDATA) in 1K chunks as required!
  332.  
  333.         i=0;
  334.  
  335.         char *bufobj=(char *)MALLOC(512*5);
  336.  
  337.         while(i<count){
  338.  
  339.                 unsigned int j;
  340.  
  341.                 sizeblock=1024;
  342.  
  343. restart:
  344.  
  345.                 for(j=0;j<posts;j++){
  346.  
  347.                         if((postbuf+j)->type>=CALL_EXT&&(postbuf+j)->type<=FIX_CODE32&&
  348.  
  349.                                         (postbuf+j)->loc>=(i+startptr)&&(postbuf+j)->loc<(i+sizeblock+startptr)){
  350.  
  351.                                 if((postbuf+j)->loc>(i+startptr+sizeblock-(am32==FALSE?2:4))){
  352.  
  353.                                         sizeblock=(postbuf+j)->loc-i-startptr;//¨§¬¥­¨âì à §¬¥à ¡«®ª 
  354.  
  355.                                         goto restart;
  356.  
  357.                                 }
  358.  
  359.                         }
  360.  
  361.                 }
  362.  
  363.                 if((i+sizeblock)>count)sizeblock=count-i;
  364.  
  365.                 obj_outLEDATA(1,i+startptr,sizeblock,data+i);
  366.  
  367.                 int ofsfix=0;
  368.  
  369.                 for(j=0;j<posts;j++){
  370.  
  371.                         if((postbuf+j)->loc>=(i+startptr)&&(postbuf+j)->loc<(i+sizeblock+startptr)){
  372.  
  373.                                 int hold=(postbuf+j)->loc-i-startptr;
  374.  
  375.                                 if((postbuf+j)->type>=CALL_32I/*POST_VAR*/&&(postbuf+j)->type<=FIX_CODE32){
  376.  
  377.                                         bufobj[ofsfix++]=(unsigned char)((am32==FALSE?0xC4:0xE4)|(hold/256));
  378.  
  379.                                         bufobj[ofsfix++]=(unsigned char)(hold%256);
  380.  
  381.                                         bufobj[ofsfix++]=0x14;
  382.  
  383.                                         bufobj[ofsfix++]=1;
  384.  
  385.                                         switch((postbuf+j)->type){
  386.  
  387.                                                 case POST_VAR:
  388.  
  389.                                                 case POST_VAR32:
  390.  
  391.                                                         bufobj[ofsfix++]=postseg;
  392.  
  393.                                                         break;
  394.  
  395.                                                 case FIX_VAR:
  396.  
  397.                                                 case FIX_VAR32:
  398.  
  399.                                                         bufobj[ofsfix++]=(unsigned char)((comfile==file_exe&&modelmem==SMALL)?2:1);
  400.  
  401.                                                         break;
  402.  
  403.                                                 case FIX_CODE:
  404.  
  405.                                                 case FIX_CODE32:
  406.  
  407.                                                         bufobj[ofsfix++]=1;
  408.  
  409.                                                         break;
  410.  
  411.                                         }
  412.  
  413.                                 }
  414.  
  415.                                 if((postbuf+j)->type>=POST_VAR32&&(postbuf+j)->type<=FIX_CODE32){
  416.  
  417.  
  418.  
  419.                                 }
  420.  
  421.                                 else if((postbuf+j)->type==CALL_EXT){
  422.  
  423.                                         int numext=findextname((postbuf+j)->num);
  424.  
  425.                                         if(numext!=0){
  426.  
  427.                                                 bufobj[ofsfix++]=(unsigned char)((am32==FALSE?0x84:0xA4)|(hold/256));
  428.  
  429.                                                 bufobj[ofsfix++]=(unsigned char)(hold%256);
  430.  
  431.                                                 bufobj[ofsfix++]=0x56;
  432.  
  433.                                                 bufobj[ofsfix++]=(unsigned char)numext;
  434.  
  435.                                         }
  436.  
  437.                                 }
  438.  
  439.                                 else if((postbuf+j)->type==EXT_VAR){
  440.  
  441.                                         int numext=findextname((postbuf+j)->num);
  442.  
  443.                                         if(numext!=0){
  444.  
  445.                                                 bufobj[ofsfix++]=(unsigned char)((am32==FALSE?0xC4:0xE4)|(hold/256));
  446.  
  447.                                                 bufobj[ofsfix++]=(unsigned char)(hold%256);
  448.  
  449.                                                 bufobj[ofsfix++]=0x16;
  450.  
  451.                                                 bufobj[ofsfix++]=1;
  452.  
  453.                                                 bufobj[ofsfix++]=(unsigned char)numext;
  454.  
  455.                                         }
  456.  
  457.                                 }
  458.  
  459.                         }
  460.  
  461.                 }
  462.  
  463.                 if(ofsfix!=0)obj_outrecord(0x9C+am32,ofsfix,(unsigned char *)bufobj);
  464.  
  465.                 i+=sizeblock;
  466.  
  467.         }
  468.  
  469.         free(bufobj);
  470.  
  471.         if(comfile==file_exe&&modelmem==SMALL){
  472.  
  473.                 i=0;
  474.  
  475.                 while(i<outptrdata){
  476.  
  477.                         if((i+1024)>outptrdata)obj_outLEDATA(2,i,outptrdata-i,outputdata+i);
  478.  
  479.                         else obj_outLEDATA(2,i,1024,outputdata+i);
  480.  
  481.                         i+=1024;
  482.  
  483.                 }
  484.  
  485.         }
  486.  
  487.         if(sobj!=FALSE){
  488.  
  489. // output end of OBJ notifier
  490.  
  491.                 string2[0]=0;
  492.  
  493.                 i=1;
  494.  
  495.         }
  496.  
  497.         else{
  498.  
  499.                 count=EntryPoint();
  500.  
  501.                 *(short *)&string2[0]=0xC1;     //£« ¢­ë© ¬®¤ã«ì ¨¬¥¥â áâ àâ®¢ë©  ¤à¥á ª®â®à ­¥«ì§ï ¬¥­ïâì.
  502.  
  503.                 *(short *)&string2[2]=0x101;
  504.  
  505.                 if(count<65536){
  506.  
  507.                         *(short *)&string2[4]=(short)count;
  508.  
  509.                         i=6;
  510.  
  511.                 }
  512.  
  513.                 else{
  514.  
  515.                         *(long *)&string2[4]=(long)count;
  516.  
  517.                         i=8;
  518.  
  519.                 }
  520.  
  521.         }
  522.  
  523.         obj_outrecord(i==8?0x8B:0x8A,i,string2);
  524.  
  525.         free(numextname);
  526.  
  527.         runfilesize=ftell(hout);
  528.  
  529.         fclose(hout);
  530.  
  531.         hout=NULL;
  532.  
  533.         return 0;
  534.  
  535. }
  536.  
  537.  
  538.  
  539. void  obj_outLEDATA(unsigned int segm,unsigned int offset,unsigned int recordlength,unsigned char *data)
  540.  
  541. {
  542.  
  543. int checksum=0;
  544.  
  545. int i;
  546.  
  547. unsigned char buf[8];
  548.  
  549.         buf[3]=(unsigned char)segm;
  550.  
  551.         if(offset>(65536-1024)){
  552.  
  553.                 *(short *)&buf[1]=(short)(recordlength+6);
  554.  
  555.                 buf[0]=0xA1;
  556.  
  557.                 *(long *)&buf[4]=(long)offset;
  558.  
  559.                 i=8;
  560.  
  561.         }
  562.  
  563.         else{
  564.  
  565.                 *(short *)&buf[1]=(short)(recordlength+4);
  566.  
  567.                 buf[0]=0xA0;
  568.  
  569.                 *(short *)&buf[4]=(short)offset;
  570.  
  571.                 i=6;
  572.  
  573.         }
  574.  
  575.         fwrite(buf,i,1,hout);
  576.  
  577.         for(i--;i>=0;i--)checksum+=buf[i];
  578.  
  579.         for(i=0;(unsigned int)i<recordlength;i++)checksum+=data[i];
  580.  
  581.         fwrite(data,recordlength,1,hout);
  582.  
  583.         checksum=-checksum;
  584.  
  585.         fwrite(&checksum,1,1,hout);
  586.  
  587. }
  588.  
  589.  
  590.  
  591. void  obj_outrecord(int recordtype,unsigned int recordlength,unsigned char *data)
  592.  
  593. // Outputs an OBJ record.
  594.  
  595. {
  596.  
  597. int checksum;
  598.  
  599. unsigned int i;
  600.  
  601.         recordlength++;
  602.  
  603.         checksum=recordtype;
  604.  
  605.         fwrite(&recordtype,1,1,hout);
  606.  
  607.         checksum+=(recordlength/256);
  608.  
  609.         checksum+=(recordlength&255);
  610.  
  611.         fwrite(&recordlength,2,1,hout);
  612.  
  613.         recordlength--;
  614.  
  615.         for(i=0;i<recordlength;i++)checksum+=data[i];
  616.  
  617.         fwrite(data,recordlength,1,hout);
  618.  
  619.         checksum=-checksum;
  620.  
  621.         fwrite(&checksum,1,1,hout);
  622.  
  623. }
  624.  
  625.  
  626.  
  627. void outeachPUBDEF(struct idrec *ptr)
  628.  
  629. {
  630.  
  631. unsigned int i;
  632.  
  633.         if(ptr!=NULL){
  634.  
  635.                 outeachPUBDEF(ptr->right);
  636.  
  637.                 if(ptr->rectok==tk_apiproc){
  638.  
  639.                         i=0;
  640.  
  641.                         for(unsigned int j=0;j<posts;j++){      //¯®¨áª ¨á¯®«ì§®¢ ­¨ï ¯à®æ¥¤ãàë
  642.  
  643.                                 if((postbuf+j)->num==(unsigned long)ptr->recnumber&&((postbuf+j)->type==CALL_32I||(postbuf+j)->type==CALL_32)){
  644.  
  645.                                         i++;
  646.  
  647.                                         (postbuf+j)->type=CALL_EXT;
  648.  
  649.                                         externnum++;
  650.  
  651.                                         if(externnum>=maxnumextname){
  652.  
  653.                                                 maxnumextname+=MAXNUMEXTNAME;
  654.  
  655.                                                 numextname=(int *)REALLOC(numextname,maxnumextname*sizeof(int));
  656.  
  657.                                         }
  658.  
  659.                                 }
  660.  
  661.                         }
  662.  
  663.                         if(i)goto nameext;
  664.  
  665.                         goto endp;
  666.  
  667.                 }
  668.  
  669.                 if(externnum!=0&&ptr->rectok==tk_undefproc&&(ptr->flag&f_extern)!=0){
  670.  
  671. nameext:
  672.  
  673.                         numextname[numextern++]=ptr->recnumber;
  674.  
  675.                         i=strlen(ptr->recid);
  676.  
  677.                         if((lenextstr+i+2)>=STRLEN){
  678.  
  679.                                 obj_outrecord(0x8c,lenextstr,&string[0]);
  680.  
  681.                                 lenextstr=0;
  682.  
  683.                         }
  684.  
  685.                         string[lenextstr++]=(unsigned char)i;
  686.  
  687.                         strcpy((char *)&string[lenextstr],ptr->recid);
  688.  
  689.                         lenextstr+=i+1;
  690.  
  691.                 }
  692.  
  693.                 else{
  694.  
  695.                         if((ptr->rectok==tk_proc||ptr->rectok==tk_interruptproc)&&ptr->recsegm>=NOT_DYNAMIC){
  696.  
  697.                                 string2[0]=(unsigned char)(am32==0?0:1);
  698.  
  699.                                 string2[1]=0x01;
  700.  
  701.                         }
  702.  
  703.                         else if((ptr->rectok>=tk_bits&&ptr->rectok<=tk_doublevar)||ptr->rectok==tk_structvar){
  704.  
  705.                                 if((ptr->flag&f_extern))goto nameext;
  706.  
  707.                                 if(am32){
  708.  
  709.                                         string2[0]=1;
  710.  
  711.                                         string2[1]=(unsigned char)(ptr->recpost==0?1:postseg);
  712.  
  713.                                 }
  714.  
  715.                                 else if(comfile==file_exe&&modelmem==SMALL){
  716.  
  717.                                         string2[0]=1;
  718.  
  719.                                         string2[1]=(unsigned char)(ptr->recpost==0?2:postseg);
  720.  
  721.                                 }
  722.  
  723.                                 else{
  724.  
  725.                                         string2[0]=(unsigned char)(ptr->recpost==0?0:1);
  726.  
  727.                                         string2[1]=(unsigned char)(ptr->recpost==0?1:postseg);
  728.  
  729.                                 }
  730.  
  731.                         }
  732.  
  733.                         else goto endp;
  734.  
  735.                         for(i=0;ptr->recid[i]!=0;i++)string2[i+3]=ptr->recid[i];
  736.  
  737.                         string2[2]=(unsigned char)i;
  738.  
  739.                         if(ptr->recnumber<65536){
  740.  
  741.                                 *(short *)&string2[i+3]=(short)ptr->recnumber;
  742.  
  743.                                 string2[i+5]=0x00;
  744.  
  745.                                 obj_outrecord(0x90,i+6,&string2[0]);
  746.  
  747.                         }
  748.  
  749.                         else{
  750.  
  751.                                 *(long *)&string2[i+3]=(long)ptr->recnumber;
  752.  
  753.                                 string2[i+7]=0x00;
  754.  
  755.                                 obj_outrecord(0x91,i+8,&string2[0]);
  756.  
  757.                         }
  758.  
  759.                 }
  760.  
  761. endp:
  762.  
  763.                 outeachPUBDEF(ptr->left);
  764.  
  765.         }
  766.  
  767. }
  768.  
  769.  
  770.  
  771.