Beispiel #1
0
//-------------------------------------------------------------------
//-------------------------------------------------------------------
int assemble ( void )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;


    curradd=0;
    nlabs=0;
    memset(mem,0x00,sizeof(mem));
    memset(mark,0x00,sizeof(mark));

    line=0;
    while(fgets(newline,sizeof(newline)-1,fpin))
    {
        line++;
        //tabs to spaces and other things
        for(ra=0;newline[ra];ra++)
        {
            if(newline[ra]<0x20)  newline[ra]=0x20;
            if(newline[ra]>=0x7F) newline[ra]=0;
        }

        //various ways to comment lines
        for(ra=0;newline[ra];ra++)
        {
            if(newline[ra]==';') newline[ra]=0;
            if(newline[ra]=='@') newline[ra]=0;
            if((newline[ra]=='/')&&(newline[ra+1]=='/')) newline[ra]=0;
            if(newline[ra]==0) break;
        }

        //skip spaces
        for(ra=0;newline[ra];ra++) if(newline[ra]!=0x20) break;
        if(newline[ra]==0) continue;

        //look for a label?
        for(rb=ra;newline[rb];rb++)
        {
            if(newline[rb]==0x20) break; //no spaces in labels
            if(newline[rb]==':') break;
        }
        if(newline[rb]==':')
        {
            //got a label
            rc=rb-ra;
            if(rc==0)
            {
                printf("<%u> Error: Invalid label\n",line);
                return(1);
            }
            rc--;
            if(rc>=LABLEN)
            {
                printf("<%u> Error: Label too long\n",line);
                return(1);
            }
            for(rb=0;rb<=rc;rb++)
            {
                lab_struct[nlabs].name[rb]=newline[ra++];
            }
            lab_struct[nlabs].name[rb]=0;
            lab_struct[nlabs].addr=0x3000+curradd;
            lab_struct[nlabs].line=line;
            lab_struct[nlabs].type=0;
            ra++;
            for(lab=0;lab<nlabs;lab++)
            {
                if(lab_struct[lab].type) continue;
                if(strcmp(lab_struct[lab].name,lab_struct[nlabs].name)==0) break;
            }
            if(lab<nlabs)
            {
                printf("<%u> Error: label [%s] already defined on line %u\n",line,lab_struct[lab].name,lab_struct[lab].line);
                return(1);
            }
            nlabs++;
            //skip spaces
            for(;newline[ra];ra++) if(newline[ra]!=0x20) break;
            if(newline[ra]==0) continue;
        }
// .word -----------------------------------------------------------
        if(strncmp(&newline[ra],".word ",6)==0)
        {
            ra+=6;
            ra=parse_immed(ra); if(ra==0) return(1);
            mem[curradd]=rx;
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// add -----------------------------------------------------------
        if(strncmp(&newline[ra],"add ",4)==0)
        {
            ra+=4;
            //add rd,rs,rx
            //add rd,rs,#imm
            ra=parse_two_regs(ra); if(ra==0) return(1);
            ra=parse_comma(ra); if(ra==0) return(1);
            if(newline[ra]=='#')
            {
                ra=parse_immed(ra+1); if(ra==0) return(1);
                if(check_simmed5(rx)) return(1);
                mem[curradd]=0x1020|(rd<<9)|(rs<<6)|(rx&0x1F);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                ra=parse_reg(ra); if(ra==0) return(1);
                mem[curradd]=0x1000|(rd<<9)|(rs<<6)|rx;
                mark[curradd]|=0x80000000;
                curradd++;
            }
            if(rest_of_line(ra)) return(1);
            continue;
        }
// and -----------------------------------------------------------
        if(strncmp(&newline[ra],"and ",4)==0)
        {
            ra+=4;
            //and rd,rs,rx
            //and rd,rs,#imm
            ra=parse_two_regs(ra); if(ra==0) return(1);
            ra=parse_comma(ra); if(ra==0) return(1);
            if(newline[ra]=='#')
            {
                ra=parse_immed(ra+1); if(ra==0) return(1);
                if(check_simmed5(rx)) return(1);
                mem[curradd]=0x5020|(rd<<9)|(rs<<6)|(rx&0x1F);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                ra=parse_reg(ra); if(ra==0) return(1);
                mem[curradd]=0x5000|(rd<<9)|(rs<<6)|rx;
                mark[curradd]|=0x80000000;
                curradd++;
            }
            if(rest_of_line(ra)) return(1);
            continue;
        }
// jmp -----------------------------------------------------------
        if(strncmp(&newline[ra],"jmp ",4)==0)
        {
            ra+=4;
            //jmp rs
            ra=parse_reg(ra); if(ra==0) return(1);
            mem[curradd]=0xC000|(rx<<6);
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// jsrr -----------------------------------------------------------
        if(strncmp(&newline[ra],"jsrr ",5)==0)
        {
            ra+=5;
            //jsrr rs
            ra=parse_reg(ra); if(ra==0) return(1);
            mem[curradd]=0x4000|(rx<<6);
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// not -----------------------------------------------------------
        if(strncmp(&newline[ra],"not ",4)==0)
        {
            ra+=4;
            //not rd,rs
            ra=parse_two_regs(ra); if(ra==0) return(1);
            mem[curradd]=0x9000|(rd<<9)|(rs<<6);
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// ret -----------------------------------------------------------
        if(strncmp(&newline[ra],"ret",3)==0)
        {
            ra+=3;
            //ret
            mem[curradd]=0xC1C0;
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// rti -----------------------------------------------------------
        if(strncmp(&newline[ra],"rti",3)==0)
        {
            ra+=3;
            //rti
            mem[curradd]=0x8000;
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// brn -----------------------------------------------------------
        if(strncmp(&newline[ra],"brn ",4)==0)
        {
            ra+=4;
            //brn offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0800|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0800;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brz -----------------------------------------------------------
        if(strncmp(&newline[ra],"brz ",4)==0)
        {
            ra+=4;
            //brz offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0400|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0400;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brp -----------------------------------------------------------
        if(strncmp(&newline[ra],"brp ",4)==0)
        {
            ra+=4;
            //brp offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0200|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0200;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brnz -----------------------------------------------------------
        if(strncmp(&newline[ra],"brnz ",5)==0)
        {
            ra+=5;
            //brnzp offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0C00|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0C00;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brnp -----------------------------------------------------------
        if(strncmp(&newline[ra],"brnp ",5)==0)
        {
            ra+=5;
            //brnp offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0A00|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0A00;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brzp -----------------------------------------------------------
        if(strncmp(&newline[ra],"brzp ",5)==0)
        {
            ra+=5;
            //brzp offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0600|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0600;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// brnzp -----------------------------------------------------------
        if(strncmp(&newline[ra],"brnzp ",6)==0)
        {
            ra+=6;
            //brnzp offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: branch too far\n",line);
                    return(1);
                }
                mem[curradd]=0x0E00|(rx&0x1FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x0E00;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// jsr -----------------------------------------------------------
        if(strncmp(&newline[ra],"jsr ",4)==0)
        {
            ra+=4;
            //jsr offset/label
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset11(rx))
                {
                    printf("<%u> Error: jsr too far\n",line);
                    return(1);
                }
                mem[curradd]=0x4800|(rx&0x07FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x4800;
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// ld -----------------------------------------------------------
        if(strncmp(&newline[ra],"ld ",3)==0)
        {
            ra+=3;
            //ld rd,offset/label
            ra=parse_reg(ra); if(ra==0) return(1);
            rd=rx;
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: ld too far\n",line);
                    return(1);
                }
                mem[curradd]=0x2000|(rd<<9)|(rx&0x01FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x2000|(rd<<9);
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// ldi -----------------------------------------------------------
        if(strncmp(&newline[ra],"ldi ",4)==0)
        {
            ra+=4;
            //ldi rd,offset/label
            ra=parse_reg(ra); if(ra==0) return(1);
            rd=rx;
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: ldi too far\n",line);
                    return(1);
                }
                mem[curradd]=0xA000|(rd<<9)|(rx&0x01FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0xA000|(rd<<9);
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// ldr -----------------------------------------------------------
        if(strncmp(&newline[ra],"ldr ",4)==0)
        {
            ra+=4;
            //ldr rd,rs,#offset
            ra=parse_two_regs(ra); if(ra==0) return(1);
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_pound(ra); if(ra==0) return(1);
            ra=parse_immed(ra); if(ra==0) return(1);
            if(rest_of_line(ra)) return(1);
            if(check_simmed6(rx)) return(1);
            mem[curradd]=0x6000|(rd<<9)|(rs<<6)|(rx&0x003F);
            mark[curradd]|=0x80000000;
            curradd++;
            continue;
        }
// lea -----------------------------------------------------------
        if(strncmp(&newline[ra],"lea ",4)==0)
        {
            ra+=4;
            //ldi rd,offset/label
            ra=parse_reg(ra); if(ra==0) return(1);
            rd=rx;
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: lea too far\n",line);
                    return(1);
                }
                mem[curradd]=0xE000|(rd<<9)|(rx&0x01FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0xE000|(rd<<9);
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// st -----------------------------------------------------------
        if(strncmp(&newline[ra],"st ",3)==0)
        {
            ra+=3;
            //st rd,offset/label
            ra=parse_reg(ra); if(ra==0) return(1);
            rd=rx;
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: st too far\n",line);
                    return(1);
                }
                mem[curradd]=0x3000|(rd<<9)|(rx&0x01FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0x3000|(rd<<9);
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// sti -----------------------------------------------------------
        if(strncmp(&newline[ra],"sti ",4)==0)
        {
            ra+=4;
            //sti rd,offset/label
            ra=parse_reg(ra); if(ra==0) return(1);
            rd=rx;
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_branch_label(ra); if(ra==0) return(0);
            if(rest_of_line(ra)) return(1);
            if(is_const)
            {
                if(check_offset9(rx))
                {
                    printf("<%u> Error: sti too far\n",line);
                    return(1);
                }
                mem[curradd]=0xB000|(rd<<9)|(rx&0x01FF);
                mark[curradd]|=0x80000000;
                curradd++;
            }
            else
            {
                mem[curradd]=0xB000|(rd<<9);
                mark[curradd]|=0x80000002;
                curradd++;
            }
            continue;
        }
// str -----------------------------------------------------------
        if(strncmp(&newline[ra],"str ",4)==0)
        {
            ra+=4;
            //str rd,rs,#offset
            ra=parse_two_regs(ra); if(ra==0) return(1);
            ra=parse_comma(ra); if(ra==0) return(1);
            ra=parse_pound(ra); if(ra==0) return(1);
            ra=parse_immed(ra); if(ra==0) return(1);
            if(rest_of_line(ra)) return(1);
            if(check_simmed6(rx)) return(1);
            mem[curradd]=0x7000|(rd<<9)|(rs<<6)|(rx&0x003F);
            mark[curradd]|=0x80000000;
            curradd++;
            continue;
        }
// trap -----------------------------------------------------------
        if(strncmp(&newline[ra],"trap ",5)==0)
        {
            ra+=5;
            //trap imm
            ra=parse_immed(ra); if(ra==0) return(1);
            if((rx&0xFF)!=rx)
            {
                printf("<%u> Error: invalid trap vector\n",line);
                return(1);
            }
            mem[curradd]=0xF000|(rx&0xFF);
            mark[curradd]|=0x80000000;
            curradd++;
            if(rest_of_line(ra)) return(1);
            continue;
        }
// -----------------------------------------------------------
        printf("<%u> Error: syntax error\n",line);
        return(1);
    }
    return(0);
}
Beispiel #2
0
/*
** Read the git-fast-import format from pIn and insert the corresponding
** content into the database.
*/
static void git_fast_import(FILE *pIn){
  ImportFile *pFile, *pNew;
  int i, mx;
  char *z;
  char *zUuid;
  char *zName;
  char *zPerm;
  char *zFrom;
  char *zTo;
  char zLine[1000];

  gg.xFinish = finish_noop;
  while( fgets(zLine, sizeof(zLine), pIn) ){
    if( zLine[0]=='\n' || zLine[0]=='#' ) continue;
    if( memcmp(zLine, "blob", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_blob;
    }else
    if( memcmp(zLine, "commit ", 7)==0 ){
      gg.xFinish();
      gg.xFinish = finish_commit;
      trim_newline(&zLine[7]);
      z = &zLine[7];

      /* The argument to the "commit" line might match either of these
      ** patterns:
      **
      **   (A)  refs/heads/BRANCHNAME
      **   (B)  refs/tags/TAGNAME
      **
      ** If pattern A is used, then the branchname used is as shown.
      ** Except, the "master" branch which is the default branch name in
      ** Git is changed to "trunk" which is the default name in Fossil.
      ** If the pattern is B, then the new commit should be on the same
      ** branch as its parent.  And, we might need to add the TAGNAME
      ** tag to the new commit.  However, if there are multiple instances
      ** of pattern B with the same TAGNAME, then only put the tag on the
      ** last commit that holds that tag.
      **
      ** None of the above is explained in the git-fast-export
      ** documentation.  We had to figure it out via trial and error.
      */
      for(i=strlen(z)-1; i>=0 && z[i]!='/'; i--){}
      gg.tagCommit = memcmp(&z[i-4], "tags", 4)==0;  /* True for pattern B */
      if( z[i+1]!=0 ) z += i+1;
      if( fossil_strcmp(z, "master")==0 ) z = "trunk";
      gg.zBranch = fossil_strdup(z);
      gg.fromLoaded = 0;
    }else
    if( memcmp(zLine, "tag ", 4)==0 ){
      gg.xFinish();
      gg.xFinish = finish_tag;
      trim_newline(&zLine[4]);
      gg.zTag = fossil_strdup(&zLine[4]);
    }else
    if( memcmp(zLine, "reset ", 4)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "checkpoint", 10)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "feature", 7)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "option", 6)==0 ){
      gg.xFinish();
    }else
    if( memcmp(zLine, "progress ", 9)==0 ){
      gg.xFinish();
      trim_newline(&zLine[9]);
      fossil_print("%s\n", &zLine[9]);
      fflush(stdout);
    }else
    if( memcmp(zLine, "data ", 5)==0 ){
      fossil_free(gg.aData); gg.aData = 0;
      gg.nData = atoi(&zLine[5]);
      if( gg.nData ){
        int got;
        gg.aData = fossil_malloc( gg.nData+1 );
        got = fread(gg.aData, 1, gg.nData, pIn);
        if( got!=gg.nData ){
          fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
        }
        gg.aData[got] = 0;
        if( gg.zComment==0 && gg.xFinish==finish_commit ){
          gg.zComment = gg.aData;
          gg.aData = 0;
          gg.nData = 0;
        }
      }
    }else
    if( memcmp(zLine, "author ", 7)==0 ){
      /* No-op */
    }else
    if( memcmp(zLine, "mark ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zMark);
      gg.zMark = fossil_strdup(&zLine[5]);
    }else
    if( memcmp(zLine, "tagger ", 7)==0 || memcmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      for(i=0; zLine[i] && zLine[i]!='<'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      z = &zLine[i+1];
      for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
      if( zLine[i]==0 ) goto malformed_line;
      zLine[i] = 0;
      fossil_free(gg.zUser);
      gg.zUser = fossil_strdup(z);
      secSince1970 = 0;
      for(i=i+2; fossil_isdigit(zLine[i]); i++){
        secSince1970 = secSince1970*10 + zLine[i] - '0';
      }
      fossil_free(gg.zDate);
      gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
      gg.zDate[10] = 'T';
    }else
    if( memcmp(zLine, "from ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zFromMark);
      gg.zFromMark = fossil_strdup(&zLine[5]);
      fossil_free(gg.zFrom);
      gg.zFrom = resolve_committish(&zLine[5]);
    }else
    if( memcmp(zLine, "merge ", 6)==0 ){
      trim_newline(&zLine[6]);
      if( gg.nMerge>=gg.nMergeAlloc ){
        gg.nMergeAlloc = gg.nMergeAlloc*2 + 10;
        gg.azMerge = fossil_realloc(gg.azMerge, gg.nMergeAlloc*sizeof(char*));
      }
      gg.azMerge[gg.nMerge] = resolve_committish(&zLine[6]);
      if( gg.azMerge[gg.nMerge] ) gg.nMerge++;
    }else
    if( memcmp(zLine, "M ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zPerm = next_token(&z);
      zUuid = next_token(&z);
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      pFile = import_find_file(zName, &i, gg.nFile);
      if( pFile==0 ){
        pFile = import_add_file();
        pFile->zName = fossil_strdup(zName);
      }
      pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
      pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
      fossil_free(pFile->zUuid);
      pFile->zUuid = resolve_committish(zUuid);
      pFile->isFrom = 0;
    }else
    if( memcmp(zLine, "D ", 2)==0 ){
      import_prior_files();
      z = &zLine[2];
      zName = rest_of_line(&z);
      dequote_git_filename(zName);
      i = 0;
      while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
        if( pFile->isFrom==0 ) continue;
        fossil_free(pFile->zName);
        fossil_free(pFile->zPrior);
        fossil_free(pFile->zUuid);
        *pFile = gg.aFile[--gg.nFile];
        i--;
      }
    }else
    if( memcmp(zLine, "C ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      mx = gg.nFile;
      nFrom = strlen(zFrom);
      while( (pFile = import_find_file(zFrom, &i, mx))!=0 ){
        if( pFile->isFrom==0 ) continue;
        pNew = import_add_file();
        pFile = &gg.aFile[i-1];
        if( strlen(pFile->zName)>nFrom ){
          pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
        }else{
          pNew->zName = fossil_strdup(pFile->zName);
        }
        pNew->isExe = pFile->isExe;
        pNew->isLink = pFile->isLink;
        pNew->zUuid = fossil_strdup(pFile->zUuid);
        pNew->isFrom = 0;
      }
    }else
    if( memcmp(zLine, "R ", 2)==0 ){
      int nFrom;
      import_prior_files();
      z = &zLine[2];
      zFrom = next_token(&z);
      zTo = rest_of_line(&z);
      i = 0;
      nFrom = strlen(zFrom);
      while( (pFile = import_find_file(zFrom, &i, gg.nFile))!=0 ){
        if( pFile->isFrom==0 ) continue;
        pNew = import_add_file();
        pFile = &gg.aFile[i-1];
        if( strlen(pFile->zName)>nFrom ){
          pNew->zName = mprintf("%s%s", zTo, pFile->zName[nFrom]);
        }else{
          pNew->zName = fossil_strdup(pFile->zName);
        }
        pNew->zPrior = pFile->zName;
        pNew->isExe = pFile->isExe;
        pNew->isLink = pFile->isLink;
        pNew->zUuid = pFile->zUuid;
        pNew->isFrom = 0;
        gg.nFile--;
        *pFile = *pNew;
        memset(pNew, 0, sizeof(*pNew));
      }
      fossil_fatal("cannot handle R records, use --full-tree");
    }else
    if( memcmp(zLine, "deleteall", 9)==0 ){
      gg.fromLoaded = 1;
    }else
    if( memcmp(zLine, "N ", 2)==0 ){
      /* No-op */
    }else

    {
      goto malformed_line;
    }
  }
  gg.xFinish();
  if( gg.hasLinks ){
    db_set_int("allow-symlinks", 1, 0);
  }
  import_reset(1);
  return;

malformed_line:
  trim_newline(zLine);
  fossil_fatal("bad fast-import line: [%s]", zLine);
  return;
}