/* * GVDR library for reading GVDR data files * Copyright (C) 1994 Michael J. Maurer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Michael Maurer * Durand Bldg - Room 232 * Stanford, CA 94305-4055 * (415) 723-1024 */ static char rcsid[]="$Id: gpds.c,v 1.3 1994/04/29 01:59:51 maurer Exp $"; /****************************************************************************** gpds.c Function: Generic PDS label routines. This file is part of the STARLab Magellan Altimeter Data Processing Software. Michael Maurer, August 1993. ******************************************************************************/ /* $Log: gpds.c,v $ * Revision 1.3 1994/04/29 01:59:51 maurer * Added #include ability for DESCRIPTION fields. * * Revision 1.2 1993/11/24 18:30:37 maurer * Added wrap field to PDS line data structure: selects characters * to wrap line after. * * Revision 1.1 1993/09/10 19:34:02 maurer * Fixed some bugs in object name matching and indenting. * * Revision 1.0 1993/08/25 20:48:30 maurer * Initial revision * */ #include #include #include #include #include "libmisc.h" #include "gpds.h" #define GPDS_C #include "gpds.p" /****************************************************************************** strrpbrk The strrpbrk subroutine returns a pointer to the last occurrence in string s1 of any character from string s2, or a NULL pointer if no character from s2 exists in s1. ******************************************************************************/ static char * strrpbrk(char *s1, char *s2) { char *s; if (!s1 || !s2) return NULL; s=s1+strlen(s1); while (s--!=s1) { if (strchr(s2,*s)) return s; } return NULL; } /****************************************************************************** strnrpbrk The strnrpbrk subroutine returns a pointer to the last occurrence in the first n characters of string s1 of any character from string s2, or a NULL pointer if no character from s2 appears in the first n characters of s1. ******************************************************************************/ static char * strnrpbrk(char *s1, char *s2, int n) { char *s; int l; if (!s1 || !s2 || n<0) return NULL; l=strlen(s1); s=s1+(lprev=L->next=NULL; return L; } static void list_free(pdslist_t *L) { pdslist_t *tail; if (tail=L) { do { tail=tail->next; free(tail->prev); } while (tail->next != L); free(tail); } } void gpds_free(pdslist_t *L) { return list_free(L); } static int list_append(pdslist_t *head, pdsentry_t *ent) { pdslist_t *new; if (head==NULL) return 1; if (head->prev==NULL) { head->prev=head->next=head; head->this= *ent; } else { if ((new=(pdslist_t *)malloc(sizeof(pdslist_t)))==NULL) return 2; new->this= *ent; new->prev=head->prev; new->next=head; head->prev->next=new; head->prev=new; } return 0; } static int has_sprintf(char *s) { int percent=0; while (*s) { if (percent) { if (*s!='%') return 1; else percent=0; } else percent=(*s=='%'); s++; } return 0; } static int gpds_rfmt1(FILE *fp, pdslist_t *head) { char line[8192]; pdsentry_t ent; if (fgets(line,sizeof(line),fp)==NULL) return 1; line[strlen(line)-1]='\0'; /* replace newline */ ent.flag = (has_sprintf(line)) ? PDS_FMT : PDS_LIT; if ((ent.fmt=(char *)malloc(strlen(line)+1))==NULL) return 2; strcpy(ent.fmt,line); ent.val=NULL; ent.wrap=NULL; if (list_append(head,&ent)) return 3; return 0; } int gpds_rfmt(FILE *fp, pdslist_t **head) { if ((*head=list_new())==NULL) return 1; while (!gpds_rfmt1(fp,*head)) ; if (!feof(fp)) return 2; return 0; } static int gpds_match(pdsentry_t *ent, char *key) { char *fmt,*first; int firstlen; fmt=ent->fmt; first=fmt+strspn(fmt," \t"); firstlen=strcspn(first," \t="); return (firstlen==strlen(key)) ? !strncmp(first,key,firstlen) : 0; } static pdsentry_t * gpds_lookup(pdslist_t *head, char *obj, char *key) { pdslist_t *p; int nfnd=0,fnd; pdsentry_t *ent=NULL; char *name=NULL; int namelen; if (!head || !head->next || !key) return NULL; p=head; do { if (gpds_match(&p->this,"OBJECT") || gpds_match(&p->this,"NAME")) { name=p->this.fmt; name+=strcspn(name,"=")+1; name+=strspn(name," \t\""); namelen=strcspn(name," \t\"\r\n"); } if (gpds_match(&p->this,"END_OBJECT")) name=NULL; fnd = (obj) ? (name && namelen==strlen(obj) && !strncmp(obj,name,namelen)) : 1; if (fnd && gpds_match(&p->this,key)) { if (nfnd==0) ent= &p->this; nfnd++; } p=p->next; } while (p!=head); if (nfnd>1) error(0,0,"[gpds_lookup] warning: multiple labels match \"%s\"",key); return ent; } int gpds_setwrap(pdslist_t *head, char *obj, char *key, char *wrap) { pdsentry_t *ent; if (!head || !key) return 1; if ((ent=gpds_lookup(head,obj,key))==NULL) return 2; ent->wrap=wrap; return 0; } int gpds_setinc(pdslist_t *head, char *obj, char *key, char *fn) { pdsentry_t *ent; if (!head || !key) return 1; if ((ent=gpds_lookup(head,obj,key))==NULL) return 2; ent->flag=PDS_INC; /* overwrite whatever is in val with filename */ if (ent->val) free(ent->val); if ((ent->val=(char *)malloc(strlen(fn)+1))==NULL) return 3; strcpy(ent->val,fn); return 0; } int gpds_sprintf(pdslist_t *head, char *obj, char *key, ...) { va_list args; pdsentry_t *ent; char line[8192]; if (!head || !key) return 1; if ((ent=gpds_lookup(head,obj,key))==NULL) return 2; va_start(args,key); if (vsprintf(line,ent->fmt,args)==EOF) return 3; va_end(args); if (strlen(line)>=sizeof(line)) return 4; if (ent->val) free(ent->val); if ((ent->val=(char *)malloc(strlen(line)+1))==NULL) return 5; strcpy(ent->val,line); return 0; } static char * gpds_str(pdsentry_t *ent) { char *s; switch (ent->flag) { case PDS_NUL: return NULL; case PDS_LIT: s=ent->fmt; break; case PDS_FMT: s=ent->val; break; default: return NULL; } if (!s) s=ent->fmt; /* for debugging: return error in real case */ return s; } #define PDS_ID_CHARS "ABCDEFGHIJKLMONPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_" char * gpds_key(pdsentry_t *ent) { int klen; char *s,*key; if ((s=gpds_str(ent))==NULL) return NULL; if ((s=strpbrk(s,PDS_ID_CHARS))==NULL) return NULL; klen=strspn(s,PDS_ID_CHARS); if ((key=(char *)malloc(klen+1))==NULL) return NULL; strncpy(key,s,klen); key[klen]='\0'; return key; } char * gpds_val(pdsentry_t *ent) { int vlen; char *s,*val; if ((s=gpds_str(ent))==NULL) return NULL; if ((s=strpbrk(s,PDS_ID_CHARS))==NULL) return NULL; s+=strspn(s,PDS_ID_CHARS); s+=strspn(s," \t"); if (*s!='=') return NULL; s++; s+=strspn(s," \t"); vlen=strlen(s)-strrspn(s," \t\r\n"); if (vlen==0) return NULL; if ((val=(char *)malloc(vlen+1))==NULL) return NULL; strncpy(val,s,vlen); val[vlen]='\0'; return val; } static int gpds_spitout(char *s, FILE *fp, pdsentry_t *ent, int reclen, int indent) { int nc,nl=0,ns; char *sw; do { for (nc=0; ncwrap && strlen(s)>reclen-indent-2 && (sw=strnrpbrk(s,ent->wrap,reclen-indent-2))) ns=sw-s+1; for (nc=indent; ncval,"r"))==NULL) { error(0,errno,"[gpds_printinc] fopen %s failed",ent->val); return 0; return 1; } while (fgets(buf,sizeof(buf),finc)) { ln++; buf[strlen(buf)-1]='\0'; /* strip linefeed */ nl=gpds_spitout(buf,fp,ent,reclen,indent); if (nl>1 && ent->wrap==NULL) error(0,0,"[gpds_printinc] warning: %s line %d wrapped to %d lines (begins \"%.20s\")", ent->val,ln,nl,buf); } fclose(finc); return 0; } static int gpds_print1(FILE *fp, pdsentry_t *ent, int reclen, int indent) { char *s; int nl; if ((s=gpds_str(ent))==NULL) s=""; if (reclen==0) reclen=indent+strlen(s)+2; if (indent>=reclen-2) return 1; if (ent->flag==PDS_INC) return gpds_printinc(fp,ent,reclen,indent); nl=gpds_spitout(s,fp,ent,reclen,indent); if (nl>1 && ent->wrap==NULL) error(0,0,"[gpds_print1] warning: line wrapped to %d lines (begins \"%.20s\")", nl,gpds_str(ent)); return 0; } int gpds_print(FILE *fp, pdslist_t *head, int reclen, int indent1) { pdslist_t *p; int indent=0,err; if (!head && !head->next) return 0; p=head; do { if (gpds_match(&p->this,"END_OBJECT")) indent-=indent1; if (err=gpds_print1(fp,&p->this,reclen,indent)) return err; if (gpds_match(&p->this,"OBJECT")) indent+=indent1; p=p->next; } while (p!=head); return 0; }