/* BASIC2026 portable PDF link annotation listing, checking and target editing. */
#define B2026_PDF_LINK_MAX 100000

typedef struct {
    int page,object_index,destination_page,valid,safe,rect_valid;
    double left,bottom,right,top;
    char *type,*target,*message;
} B2026PdfLink;

typedef struct { B2026PdfLink *items;int count,capacity; } B2026PdfLinkList;

static void b2026_pdf_link_free(B2026PdfLinkList *list){int i;if(list==NULL)return;for(i=0;i<list->count;++i){free(list->items[i].type);free(list->items[i].target);free(list->items[i].message);}free(list->items);memset(list,0,sizeof(*list));}
static int b2026_pdf_link_push(B2026PdfLinkList *list,B2026PdfLink *item){if(list->count>=B2026_PDF_LINK_MAX)return 0;if(list->count==list->capacity){int cap=list->capacity?list->capacity*2:32;B2026PdfLink*p;if(cap>B2026_PDF_LINK_MAX)cap=B2026_PDF_LINK_MAX;p=(B2026PdfLink*)realloc(list->items,(size_t)cap*sizeof(*p));if(p==NULL)return 0;list->items=p;list->capacity=cap;}list->items[list->count++]=*item;return 1;}
static void b2026_pdf_link_pair_number(const char*t,const char*jp,const char*en,double v){hash_set_number(t,jp,v);hash_set_number(t,en,v);}
static void b2026_pdf_link_pair_string(const char*t,const char*jp,const char*en,const char*v){hash_set_string(t,jp,v!=NULL?v:"");hash_set_string(t,en,v!=NULL?v:"");}
static void b2026_pdf_link_key(char*out,size_t cap,int index,const char*field){snprintf(out,cap,"%d,%s",index,field);}
static void b2026_pdf_link_index_number(const char*t,int i,const char*jp,const char*en,double v){char k[128];b2026_pdf_link_key(k,sizeof(k),i,jp);hash_set_number(t,k,v);b2026_pdf_link_key(k,sizeof(k),i,en);hash_set_number(t,k,v);}
static void b2026_pdf_link_index_string(const char*t,int i,const char*jp,const char*en,const char*v){char k[128];b2026_pdf_link_key(k,sizeof(k),i,jp);hash_set_string(t,k,v!=NULL?v:"");b2026_pdf_link_key(k,sizeof(k),i,en);hash_set_string(t,k,v!=NULL?v:"");}

static int b2026_pdf_link_uri_check(const char *uri,int *safe,const char **message){const unsigned char*p=(const unsigned char*)(uri!=NULL?uri:"");size_t n=strlen((const char*)p),i,scheme=0;*safe=0;if(n==0U){*message="EMPTY_TARGET / リンク先が空です";return 0;}if(n>8192U){*message="TARGET_TOO_LONG / リンク先が長すぎます";return 0;}for(i=0;i<n;++i)if(p[i]<0x20U||p[i]==0x7FU){*message="CONTROL_CHARACTER / 制御文字が含まれています";return 0;}while(scheme<n&&(isalnum(p[scheme])||p[scheme]=='+'||p[scheme]=='-'||p[scheme]=='.'))++scheme;if(scheme==0U||scheme>=n||p[scheme]!=':'){*message="SCHEME_MISSING / URI方式がありません";return 0;}if((scheme==4U&&b2026_strncasecmp((const char*)p,"HTTP",4U)==0)||(scheme==5U&&b2026_strncasecmp((const char*)p,"HTTPS",5U)==0)||(scheme==6U&&b2026_strncasecmp((const char*)p,"MAILTO",6U)==0)||(scheme==3U&&b2026_strncasecmp((const char*)p,"FTP",3U)==0)){*safe=1;*message="OK";return 1;}if((scheme==10U&&b2026_strncasecmp((const char*)p,"JAVASCRIPT",10U)==0)||(scheme==4U&&b2026_strncasecmp((const char*)p,"DATA",4U)==0)||(scheme==4U&&b2026_strncasecmp((const char*)p,"FILE",4U)==0)){*message="UNSAFE_SCHEME / 危険なURI方式です";return 1;}*message="UNSUPPORTED_SCHEME / 未対応のURI方式です";return 1;}

static int b2026_pdf_link_action_body(B2026PdfDocument*doc,const unsigned char*body,size_t n,const unsigned char**out,size_t*out_n){B2026PdfKeyRange r;int num,gen,oi;if(!b2026_pdf_tf_find_key(body,n,"/A",&r)||!r.found)return 0;if(b2026_pdf_tf_ref(body+r.value_start,r.value_end-r.value_start,&num,&gen)&&(oi=b2026_pdf_object_lookup(doc,num,gen))>=0){*out=doc->objects[oi].body;*out_n=doc->objects[oi].body_length;return 1;}*out=body+r.value_start;*out_n=r.value_end-r.value_start;return 1;}
static char*b2026_pdf_link_dict_string(B2026PdfDocument*doc,const unsigned char*body,size_t n,const char*key){B2026PdfKeyRange r;if(!b2026_pdf_tf_find_key(body,n,key,&r)||!r.found)return NULL;return b2026_pdf_parse_string_value(doc,body,n,r.value_start,0);}

static int b2026_pdf_link_one(B2026PdfDocument*doc,const unsigned char*body,size_t n,int object_index,int page,B2026PdfLinkList*list){B2026PdfLink item;const unsigned char*action=NULL;size_t action_n=0U;char*subtype=NULL,*kind=NULL,*value=NULL;double rect[4],unit=1.0;int rect_count,safe=0;B2026PdfKeyRange direct_dest;const char*message="OK";memset(&item,0,sizeof(item));subtype=b2026_pdf_dict_name(body,n,"/Subtype");if(subtype==NULL||strcmp(subtype,"Link")!=0){free(subtype);return 1;}free(subtype);item.page=page;item.object_index=object_index;item.safe=1;rect_count=b2026_pdf_number_array(body,n,"/Rect",rect,4);if(rect_count==4){if(b2026_pdf_page_direct_number(doc,doc->page_objects[page-1],"/UserUnit",&unit)<=0)unit=1.0;item.left=fmin(rect[0],rect[2])*unit;item.bottom=fmin(rect[1],rect[3])*unit;item.right=fmax(rect[0],rect[2])*unit;item.top=fmax(rect[1],rect[3])*unit;item.rect_valid=item.right>item.left&&item.top>item.bottom;}if(b2026_pdf_tf_find_key(body,n,"/Dest",&direct_dest)&&direct_dest.found){item.type=b2026_strdup_simple("INTERNAL");item.destination_page=b2026_pdf_bm_dest_page(doc,body,n,"/Dest");item.valid=item.destination_page>0;item.target=b2026_strdup_simple("");if(!item.valid){item.safe=0;message="DESTINATION_UNRESOLVED / 移動先ページを解決できません";}}
    else if(b2026_pdf_link_action_body(doc,body,n,&action,&action_n)){kind=b2026_pdf_dict_name(action,action_n,"/S");if(kind!=NULL&&strcmp(kind,"URI")==0){item.type=b2026_strdup_simple("URI");value=b2026_pdf_link_dict_string(doc,action,action_n,"/URI");item.target=b2026_strdup_simple(value!=NULL?value:"");item.valid=b2026_pdf_link_uri_check(item.target,&safe,&message);item.safe=safe;}else if(kind!=NULL&&strcmp(kind,"GoTo")==0){item.type=b2026_strdup_simple("INTERNAL");item.destination_page=b2026_pdf_bm_dest_page(doc,action,action_n,"/D");item.target=b2026_strdup_simple("");item.valid=item.destination_page>0;message=item.valid?"OK":"DESTINATION_UNRESOLVED / 移動先ページを解決できません";}else if(kind!=NULL&&strcmp(kind,"GoToR")==0){item.type=b2026_strdup_simple("REMOTE");value=b2026_pdf_link_dict_string(doc,action,action_n,"/F");item.target=b2026_strdup_simple(value!=NULL?value:"");item.valid=value!=NULL&&*value!='\0';item.safe=0;message="REMOTE_PDF / 外部PDFリンクです";}else if(kind!=NULL&&strcmp(kind,"Launch")==0){item.type=b2026_strdup_simple("LAUNCH");value=b2026_pdf_link_dict_string(doc,action,action_n,"/F");item.target=b2026_strdup_simple(value!=NULL?value:"");item.valid=value!=NULL&&*value!='\0';item.safe=0;message="LAUNCH_ACTION / 起動アクションです";}else{item.type=b2026_strdup_simple(kind!=NULL?kind:"UNKNOWN");item.target=b2026_strdup_simple("");item.valid=0;item.safe=0;message="UNSUPPORTED_ACTION / 未対応のリンク動作です";}free(kind);free(value);}else{item.type=b2026_strdup_simple("UNKNOWN");item.target=b2026_strdup_simple("");item.valid=0;item.safe=0;message="TARGET_MISSING / リンク先がありません";}
    if(!item.rect_valid){item.valid=0;message="RECT_INVALID / リンク領域が不正です";}item.message=b2026_strdup_simple(message);if(item.type==NULL||item.target==NULL||item.message==NULL||!b2026_pdf_link_push(list,&item)){free(item.type);free(item.target);free(item.message);return 0;}return 1;}

static int b2026_pdf_link_page(B2026PdfDocument*doc,int page,B2026PdfLinkList*list){B2026PdfObject*po=&doc->objects[doc->page_objects[page-1]];B2026PdfKeyRange r;const unsigned char*array;size_t n,p,end;char*owned=NULL;if(!b2026_pdf_tf_find_key(po->body,po->body_length,"/Annots",&r))return 0;if(!r.found)return 1;owned=b2026_pdf_tf_value_copy(doc,po->body+r.value_start,r.value_end-r.value_start,1);if(owned==NULL)return 0;array=(const unsigned char*)owned;n=strlen(owned);p=b2026_pdf_tf_space(array,n,0U);if(p>=n||array[p]!='['){free(owned);return 0;}end=b2026_pdf_tf_value_end(array,n,p,0);++p;while(p<end){p=b2026_pdf_tf_space(array,end,p);if(p>=end||array[p]==']')break;if(p+1U<end&&array[p]=='<'&&array[p+1U]=='<'){size_t q=b2026_pdf_tf_value_end(array,end,p,0);if(q<=p||!b2026_pdf_link_one(doc,array+p,q-p,-1,page,list)){free(owned);return 0;}p=q;continue;}if(isdigit(array[p])){char*e;long num=strtol((const char*)array+p,&e,10),gen;size_t q=b2026_pdf_tf_space(array,end,(size_t)(e-(char*)array)),u;int oi;if(q<end&&isdigit(array[q])){gen=strtol((const char*)array+q,&e,10);u=b2026_pdf_tf_space(array,end,(size_t)(e-(char*)array));if(u<end&&array[u]=='R'&&num>0&&num<=INT_MAX&&gen>=0&&gen<=INT_MAX&&(oi=b2026_pdf_object_lookup(doc,(int)num,(int)gen))>=0){if(!b2026_pdf_link_one(doc,doc->objects[oi].body,doc->objects[oi].body_length,oi,page,list)){free(owned);return 0;}p=u+1U;continue;}}}++p;}free(owned);return 1;}

static int b2026_pdf_link_collect(B2026PdfDocument*doc,int requested_page,B2026PdfLinkList*list){int p,first=1,last=doc->page_count;if(requested_page>0)first=last=requested_page;for(p=first;p<=last;++p)if(!b2026_pdf_link_page(doc,p,list))return 0;return 1;}

static int b2026_pdf_link_to_hash(const char*target,B2026PdfDocument*doc,B2026PdfLinkList*list,const char*operation){int i,valid=0,invalid=0,safe=0,unsafe=0,external=0,internal=0,unsupported=0;HashVariable*h=ensure_local_hash(get_hash_frame(target),target);if(h==NULL)return 0;clear_hash_entries(h);for(i=0;i<list->count;++i){B2026PdfLink*x=&list->items[i];if(x->valid)++valid;else ++invalid;if(x->safe)++safe;else ++unsafe;if(strcmp(x->type,"URI")==0)++external;else if(strcmp(x->type,"INTERNAL")==0)++internal;else ++unsupported;b2026_pdf_link_index_number(target,i+1,"ページ","page",(double)x->page);b2026_pdf_link_index_string(target,i+1,"種類","type",x->type);b2026_pdf_link_index_string(target,i+1,"リンク先","target",x->target);b2026_pdf_link_index_number(target,i+1,"移動先ページ","destinationPage",(double)x->destination_page);b2026_pdf_link_index_number(target,i+1,"左","left",x->rect_valid?x->left:null_value());b2026_pdf_link_index_number(target,i+1,"下","bottom",x->rect_valid?x->bottom:null_value());b2026_pdf_link_index_number(target,i+1,"右","right",x->rect_valid?x->right:null_value());b2026_pdf_link_index_number(target,i+1,"上","top",x->rect_valid?x->top:null_value());b2026_pdf_link_index_number(target,i+1,"横幅","width",x->rect_valid?x->right-x->left:null_value());b2026_pdf_link_index_number(target,i+1,"縦幅","height",x->rect_valid?x->top-x->bottom:null_value());b2026_pdf_link_index_number(target,i+1,"有効","valid",(double)x->valid);b2026_pdf_link_index_number(target,i+1,"安全","safe",(double)x->safe);b2026_pdf_link_index_string(target,i+1,"検査結果","message",x->message);}b2026_pdf_link_pair_number(target,"成功","ok",1.0);b2026_pdf_link_pair_string(target,"状態","status",(invalid||unsafe)?"WARNING":"OK");b2026_pdf_link_pair_number(target,"件数","count",(double)list->count);b2026_pdf_link_pair_number(target,"総ページ数","pageCount",(double)doc->page_count);b2026_pdf_link_pair_number(target,"有効数","validCount",(double)valid);b2026_pdf_link_pair_number(target,"無効数","invalidCount",(double)invalid);b2026_pdf_link_pair_number(target,"安全数","safeCount",(double)safe);b2026_pdf_link_pair_number(target,"注意数","warningCount",(double)unsafe);b2026_pdf_link_pair_number(target,"外部リンク数","externalCount",(double)external);b2026_pdf_link_pair_number(target,"内部リンク数","internalCount",(double)internal);b2026_pdf_link_pair_number(target,"未対応数","unsupportedCount",(double)unsupported);b2026_pdf_link_pair_string(target,"検査方式","checkMode",strcmp(operation,"CHECKLINKS")==0?"STRUCTURE_ONLY":"LIST");return 1;}

static int b2026_pdf_link_error(int code,const char*op,const char*path,const char*detail){char msg[4096];snprintf(msg,sizeof(msg),"PDF.%s failed: path=%s: %s",op,path!=NULL?path:"",detail!=NULL?detail:"unknown error / 不明なエラー");basic_set_error_logged(code,msg,op,current_source_path,current_line,"PDF");b2026_try_append_log_line("__PDF_ERROR.log",msg);return 0;}

static int b2026_pdf_link_get(const char*target,const char*operation,int argc,const B2026PdfArg*args){B2026PdfDocument doc;B2026PdfLinkList list;HashVariable*h;int rc,page=0;memset(&doc,0,sizeof(doc));memset(&list,0,sizeof(list));if(target==NULL||(h=ensure_local_hash(get_hash_frame(target),target))==NULL)return 0;clear_hash_entries(h);if((argc!=1&&argc!=2)||args[0].kind!=1||args[0].text==NULL||(argc==2&&(args[1].kind!=0||!isfinite(args[1].number)||floor(args[1].number)!=args[1].number)))return b2026_pdf_link_error(4403,operation,"","path and optional integer page are required / PDFパスと省略可能な整数ページ番号が必要です");rc=b2026_pdf_load(&doc,args[0].text,0);if(rc<=0){b2026_pdf_link_pair_number(target,"成功","ok",0.0);b2026_pdf_link_pair_string(target,"状態","status","FAILED");b2026_pdf_link_error(4404,operation,args[0].text,b2026_pdf_load_error(rc));goto done;}if(argc==2){double requested=args[1].number;if(requested<1.0){page=1;b2026_pdf_log_warning("リンク検査ページを1ページ目へ調整しました。 / Link inspection page was adjusted to page 1.");}else if(requested>(double)doc.page_count){page=doc.page_count;b2026_pdf_log_warning("リンク検査ページを最終ページへ調整しました。 / Link inspection page was adjusted to the last page.");}else page=(int)requested;}if(!b2026_pdf_link_collect(&doc,page,&list)||!b2026_pdf_link_to_hash(target,&doc,&list,operation)){clear_hash_entries(h);b2026_pdf_link_error(4405,operation,args[0].text,"link annotation structure is invalid / リンク注釈構造が不正です");goto done;}b2026_pdf_link_free(&list);b2026_pdf_document_free(&doc);return 1;done:b2026_pdf_link_free(&list);b2026_pdf_document_free(&doc);return 0;}

static HashEntry*b2026_pdf_link_change_entry(HashVariable*h,int i,const char*jp,const char*en){char k[128];HashEntry*e;b2026_pdf_link_key(k,sizeof(k),i,jp);e=find_hash_entry(h,k);if(e!=NULL)return e;b2026_pdf_link_key(k,sizeof(k),i,en);return find_hash_entry(h,k);}
static char*b2026_pdf_link_hex(const char*s){static const char*d="0123456789ABCDEF";size_t n=strlen(s),i;if(n>(SIZE_MAX-3U)/2U)return NULL;{char*out=(char*)malloc(n*2U+3U);if(out==NULL)return NULL;out[0]='<';for(i=0;i<n;++i){unsigned char c=(unsigned char)s[i];out[1U+i*2U]=d[c>>4];out[2U+i*2U]=d[c&15U];}out[1U+n*2U]='>';out[2U+n*2U]='\0';return out;}}

static int b2026_pdf_link_apply_changes(B2026PdfDocument*doc,B2026PdfLinkList*list,HashVariable*h,unsigned char**changed_out,int*changed_count){HashEntry*ce=b2026_pdf_tf_entry(h,"件数","count");unsigned char*changed;int count,i;if(ce==NULL||ce->value.type!=TYPE_NUMBER||!isfinite(ce->value.val.number)||floor(ce->value.val.number)!=ce->value.val.number||ce->value.val.number<1.0||ce->value.val.number>B2026_PDF_LINK_MAX)return 0;count=(int)ce->value.val.number;changed=(unsigned char*)calloc((size_t)(list->count>0?list->count:1),1U);if(changed==NULL)return 0;for(i=1;i<=count;++i){HashEntry*ne=b2026_pdf_link_change_entry(h,i,"番号","index"),*te=b2026_pdf_link_change_entry(h,i,"種類","type"),*ue=b2026_pdf_link_change_entry(h,i,"URI","uri"),*pe=b2026_pdf_link_change_entry(h,i,"ページ","page");int index;const char*type=NULL;if(ne==NULL||ne->value.type!=TYPE_NUMBER||!isfinite(ne->value.val.number)||floor(ne->value.val.number)!=ne->value.val.number||ne->value.val.number<1.0||ne->value.val.number>(double)list->count){free(changed);return 0;}index=(int)ne->value.val.number;if(changed[index-1]||list->items[index-1].object_index<0){free(changed);return 0;}if(te!=NULL&&te->value.type!=TYPE_NUMBER)type=hash_value_as_text(&te->value);if(type==NULL)type=ue!=NULL?"URI":(pe!=NULL?"PAGE":NULL);if(type==NULL){free(changed);return 0;}if(b2026_strcasecmp(type,"URI")==0||strcmp(type,"外部")==0||strcmp(type,"外部リンク")==0){const char*uri;const char*message;int safe;char*hex,*action,*expected;if(ue==NULL||ue->value.type==TYPE_NUMBER){free(changed);return 0;}uri=hash_value_as_text(&ue->value);if(!b2026_pdf_link_uri_check(uri,&safe,&message)||!safe){free(changed);return 0;}expected=b2026_strdup_simple(uri);if(expected==NULL){free(changed);return 0;}hex=b2026_pdf_link_hex(uri);if(hex==NULL){free(expected);free(changed);return 0;}action=(char*)malloc(strlen(hex)+32U);if(action==NULL){free(hex);free(expected);free(changed);return 0;}sprintf(action,"<< /S /URI /URI %s >>",hex);free(hex);if(!b2026_pdf_tf_set_key(doc,list->items[index-1].object_index,"/Dest",NULL,1)||!b2026_pdf_tf_set_key(doc,list->items[index-1].object_index,"/A",action,0)){free(action);free(expected);free(changed);return 0;}free(action);free(list->items[index-1].type);free(list->items[index-1].target);list->items[index-1].type=b2026_strdup_simple("URI");list->items[index-1].target=expected;list->items[index-1].destination_page=0;list->items[index-1].valid=1;list->items[index-1].safe=1;if(list->items[index-1].type==NULL){free(changed);return 0;}}else if(b2026_strcasecmp(type,"PAGE")==0||b2026_strcasecmp(type,"INTERNAL")==0||strcmp(type,"内部")==0||strcmp(type,"内部リンク")==0){double page;char dest[96];char*expected_type,*expected_target;if(pe==NULL||pe->value.type!=TYPE_NUMBER||!isfinite(pe->value.val.number)||floor(pe->value.val.number)!=pe->value.val.number){free(changed);return 0;}page=pe->value.val.number;if(page<1.0){page=1.0;b2026_pdf_log_warning("リンク先ページを1ページ目へ補正しました。 / Link destination was clamped to page 1.");}else if(page>(double)doc->page_count){page=(double)doc->page_count;b2026_pdf_log_warning("リンク先ページを最終ページへ補正しました。 / Link destination was clamped to the last page.");}snprintf(dest,sizeof(dest),"[%d 0 R /Fit]",doc->objects[doc->page_objects[(int)page-1]].old_number);if(!b2026_pdf_tf_set_key(doc,list->items[index-1].object_index,"/A",NULL,1)||!b2026_pdf_tf_set_key(doc,list->items[index-1].object_index,"/Dest",dest,0)){free(changed);return 0;}expected_type=b2026_strdup_simple("INTERNAL");expected_target=b2026_strdup_simple("");if(expected_type==NULL||expected_target==NULL){free(expected_type);free(expected_target);free(changed);return 0;}free(list->items[index-1].type);free(list->items[index-1].target);list->items[index-1].type=expected_type;list->items[index-1].target=expected_target;list->items[index-1].destination_page=(int)page;list->items[index-1].valid=1;list->items[index-1].safe=1;}else{free(changed);return 0;}changed[index-1]=1U;}*changed_out=changed;*changed_count=count;return 1;}

static int b2026_pdf_link_verify(const char*path,B2026PdfLinkList*before,unsigned char*changed){B2026PdfDocument doc;B2026PdfLinkList after;int rc,i,ok=0;memset(&doc,0,sizeof(doc));memset(&after,0,sizeof(after));rc=b2026_pdf_load(&doc,path,0);if(rc<=0||!b2026_pdf_link_collect(&doc,0,&after)||after.count!=before->count)goto done;for(i=0;i<after.count;++i)if(changed[i]&&(!after.items[i].valid||!after.items[i].safe||strcmp(after.items[i].type,before->items[i].type)!=0||strcmp(after.items[i].target,before->items[i].target)!=0||after.items[i].destination_page!=before->items[i].destination_page))goto done;ok=1;done:b2026_pdf_link_free(&after);b2026_pdf_document_free(&doc);return ok;}

static const char*b2026_pdf_link_edit(const char*operation,int argc,const B2026PdfArg*args){int separate,source_index,rc,i,changed_count=0;const char*source;char*output=NULL,*stage=NULL;HashVariable*h=NULL;B2026PdfDocument doc;B2026PdfLinkList list;B2026PdfPageList pages;unsigned char*changed=NULL;const char*result;memset(&doc,0,sizeof(doc));memset(&list,0,sizeof(list));memset(&pages,0,sizeof(pages));if((argc!=2&&argc!=3)||!b2026_pdf_tf_hash(&args[argc-1],&h))return b2026_pdf_fail(4406,"","CHANGELINKS requires path$, changes{} or output$, source$, changes{} / リンク変更の引数が正しくありません");separate=argc==3;source_index=separate?1:0;if(args[0].kind!=1||args[0].text==NULL||args[source_index].kind!=1||args[source_index].text==NULL)return b2026_pdf_fail(4406,"","PDF path must be a string / PDFパスは文字列で指定してください");source=args[source_index].text;output=b2026_pdf_output_path(args[0].text);if(output==NULL)goto memory_fail;rc=b2026_pdf_load(&doc,source,1);if(rc<=0){b2026_pdf_link_error(4407,operation,source,b2026_pdf_load_error(rc));goto fail;}if(!b2026_pdf_link_collect(&doc,0,&list)){b2026_pdf_link_error(4408,operation,source,"link annotation structure is invalid / リンク注釈構造が不正です");goto fail;}if(!b2026_pdf_link_apply_changes(&doc,&list,h,&changed,&changed_count)){b2026_pdf_link_error(4409,operation,source,"link change data is invalid, unsafe, duplicate, or refers to a direct annotation / リンク変更データが不正・危険・重複、または直接注釈を参照しています");goto fail;}if(!b2026_pdf_tf_set_key(&doc,doc.root_object,"/Type",NULL,1)||!b2026_pdf_tf_set_key(&doc,doc.root_object,"/Pages",NULL,1))goto memory_fail;for(i=0;i<doc.page_count;++i)if(!b2026_pdf_pages_push(&pages,&doc,doc.page_objects[i],-1))goto memory_fail;stage=b2026_atomic_temp_path(output);if(stage==NULL||!b2026_pdf_write_output(stage,&doc,1,&pages,0,0,1)){b2026_pdf_link_error(4410,operation,output,"link-edited PDF could not be staged or exceeded 2 GiB / リンク変更PDFを準備できないか2GiB上限を超えました");goto fail;}if(!b2026_pdf_link_verify(stage,&list,changed)){b2026_pdf_link_error(4411,operation,output,"post-write link verification failed / 保存後のリンク検証に失敗しました");goto fail;}if(!b2026_atomic_commit_file(stage,output)){b2026_pdf_link_error(4412,operation,output,"verified PDF could not be committed / 検証済みPDFを保存先へ反映できません");goto fail;}free(stage);stage=NULL;result=runtime_temp_string_copy(output);free(output);free(changed);free(pages.items);b2026_pdf_link_free(&list);b2026_pdf_document_free(&doc);(void)changed_count;return result;memory_fail:b2026_pdf_link_error(4413,operation,source,"out of memory / メモリ不足です");fail:if(stage!=NULL){b2026_atomic_discard_file(stage);free(stage);}free(output);free(changed);free(pages.items);b2026_pdf_link_free(&list);b2026_pdf_document_free(&doc);return runtime_temp_string_copy("");}
