a99  V32.6
allegro Windows Hauptprogramm
 Alle Klassen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
konfig.cpp
gehe zur Dokumentation dieser Datei
1 // KONFIG.CPP : Konfigurationsdatei (c) UB Braunschweig 1995
2 // 1995-08-19 mit Verify und Validate
3 // Copyright 2011 Universitätsbibliothek Braunschweig, more see bottom
4 
5 // BACKGROUND and PHRASE MANAGEMENT
6 // are in UTILITY.CPP
7 
8 
9 #include "konfig.hpp" // Eigenschaften und Methoden
10 
11 
12 // FUNKTIONEN
13 
14 // KoVerify() : Ist die Kategorienummer gueltig?
15 // KoValidate() : Ist der Feldinhalt ok?
16 // KoGetlabel() : Klartext-Label zu einer Feldnummer ermitteln
17 // KoArticle() : Beginnt der Text mit einem Artikel?
18 // KoSubCheck() : Sind die Unterfelder ok?
19 
20 // *********** Hauptfunktion: CFG-Datei einlesen
21 
22 // Ergebnis: kat[1] = Basisadresse der Deskriptoren
23 // qs = Basis der Abfrageliste (DOS, f. a99 wenig relevant)
24 
25 KONFIG::KONFIG(char *cfgName, char *dbDir) // Konstruktor %% DOS: NACORE.C
26 {
27  FILE *cfgFile;
28  char kname[PATH_SIZE]; // Dateiname der CFG
29  CHAR cline[256]; // Eingelesene Zeile aus CFG
30 
31 // Eigenschaften des KONFIG-Objekts
32  kat=(CHAR**)NULL;
33  katlist=(CHAR*)NULL;
34  qs=(CHAR*)NULL;
35  multcode='a'; // #nn, #nna, #nnb, ...
36  CHAR *src;
37  int i;
38 
39  *Aerror=0; // Fuer Fehlermeldungen (glob. Var.)
40 
41  schema=tolower(*cfgName);
42 // Dateinamen zuerst mit $ suchen
43  sprintf(kname,"$%s.cfg%c",cfgName,0);
44 
45  cfgFile=SyOpen(kname,"r",dbDir);
46 // dann ohne $
47  if (!cfgFile)
48  {
49  cfgFile=SyOpen(kname+1,"r",dbDir);
50  }
51  if (!cfgFile) // gibt's nicht
52  {
53  sprintf(Aerror,"Datei %s in %s nicht gefunden%c",kname,dbDir,0);
54  return;
55  }
56 
57  *dat_e=*dat_n=0;
58  strcpy(dat_g,"wrzc"); // $$000121 to prevent trouble
59  strcpy(ind_g,"9?5");
60 
61  // Platz bereitstellen: Defaults fuer Speicherbereiche
62  // werden durch die m-Befehle evtl. modifiziert
63  parmem=40000; // parameter memory, mP=...
64  kdim=800; // number of descriptors
65  gdim=2500; // max number of fields in workspace
66  gspace=48000; // record space
67 
68  numk=1; // Anz. Deskriptoren (#-Zeilen in CFG)
69 
70  qs=(CHAR*)NULL; // Speicherbereich f. Deskrp.
71  tgl=2;
72  TGL=0;
73  *art=NL; // article list
74  lz=0;
75  skt=4; // erste Textposition
76  KC='#';
77  SF=(CHAR)31;
78  FIL=(CHAR)219;
79  NS=(CHAR)170;
80  NN='@';
81  JA='y';
82  NEIN='n';
83  nsm=0; // nonsort mode
84  cline[254]=0;
85  cline[253]=34;
86  cline[252]=39; // zur Sicherheit
87  DL=17; // Datumslaenge
88 
89 // Zeilen jeweils in cline einlesen und verarbeiten
90  while (fgets((char*)cline,254,cfgFile)!=NULL && *cline!='x')
91  {
92  if (!*cline || *cline==' ') continue; // empty or comment
93  if (*cline!='#')
94  {
95  i=0;
96  while (cline[i] && i!='"') ++i;
97  if (i>skt) i=skt;
98  }
99  else
100  {
101  i=tgl+2;
102  if (cline[i]==' ') ++i;
103  }
104 // Kommentare entfernen: Doppelspatium leitet Kommentar ein!
105  UtRemCom((char*)cline+i-1); // jedoch nn ".. .." ist erlaubt
106 
107 // CFG-Zeile verarbeiten
108  {
109  CHAR *wi;
110  int pos,i;
111  int prop=(Apgnb<'4')?0:7;
112  CHAR *c1;
113  c1=cline+1;
114  while (*c1==' ') ++c1;
115  s_cfg((char *)cline);
116  switch (*cline)
117  {
118  case NL :
119  case ' ': // comment line
120  case 'x':
121  case TAB:
122  case 13:
123  case 10:
124  break;
125  case ':': // drives obsolete
126  break;
127 
128  case '#': // legal kat numbers with routine codes
129  {
130  if (numk==1) // initialize record workspace
131  {
132  kat= new CHAR*[kdim];
133  if (!Aflag) Aspace=new CHAR[gspace];
134  Aflag=1;
135  kat[1]=Aspace;
136  }
137  src=kat[numk]; // base address of tag descriptor
138 
139  i=0;
140  //******* nur f. CFG der alten Art vor V13 *********
141  if (!TGL) // old .CFG is handled differently:
142  {
143  int j;
144  while (cline[++i])
145  {
146  j=2;
147  while (j<16) src[++j]=0;
148  *src=cline[i];
149  src[1]=cline[++i];
150  //  auf 0 setzen
151  src[5]=0;
152  src[2]=7;
153  src[4]=12;
154  src[12]=' ';
155  src[13]=cline[++i];
156  if (cline[i]<'[') src[2]=5|prop; // check codes A..Z
157  src=kat[++numk]=src+15;
158  }
159  break;
160  }
161  /******** end of obsolete part *****************************/
162 
163  strncpy((char *)kat[numk],(char *)c1,tgl);
164  pos=tgl;
165  wi=cline+tgl+1;
166  src[pos++]=7; /* default properties :
167  bit a 1 here means:
168  1 : enterable
169  2 : alterable
170  4 : visible
171  8 : multiple spaces allowed */
172  src[pos++]=0; // default type : variable length
173  while (i++<7) src[pos++]=0; // Vorbesetzung
174  i=tgl+2; // name beginnt bei src+8
175  // src[8]=0 wenn kein Name
176  // ... pos wird dann als Offset-Zaehler beim Einlesen benutzt; am Ende:
177  if (*wi=='"') while (*++wi!='"' && *wi) src[pos++]=*wi; // field name
178  else --wi;
179  src[pos++]=0;
180  wi++; // jetzt ist pos >= 9
181 // Was steht hinter "..."? Wenn Dreieck, dann:
182  if (*wi=='') while (*wi) // Typ  = variables Feld mit Teilfeldern
183  {
184  switch (*++wi) // P255 is default
185  {
186  case 'P': // set properties flags
187  src[tgl]=atoi(wi+1)|prop;
188  break;
189  case 'F': // Fixed Field pattern
190  src[i-1]=pos;
191  break;
192  case 'C': // Check routine
193  src[i]=pos;
194  break;
195  case 'M': // Multicodes allowed
196  src[i+1]=pos;
197  break;
198  case 'A': // allowed subfields
199  src[i+2]=pos;
200  break;
201  case 'N':
202  src[i+3]=pos;
203  break;
204  case 'R':
205  src[i+4]=pos;
206  break;
207  case 'I':
208  src[i+5]=pos;
209  break;
210  case 'J':
211  src[i+6]=pos;
212  break;
213  default:
214  break;
215  }
216  while (*++wi!='' && *wi) if (*wi!='"') src[pos++]=*wi;
217  src[pos++]=0;
218  }
219  /* Vererbung: noch nicht implementiert $$24.4.93, lohnt wohl nicht
220  else if(*wi=='#') // Typ # : auf wi+1 steht die zu beerbende Kategorie **
221  { int j, k;
222  i=0; // copy all parts from the other field descriptor **
223  while(i<numk) if(!strncmp(wi+1,kat[i],tgl)) break; else ++i;
224  if(i==numk) { sprintf(Aerror,"KonfigZeile %s nicht ausfuehrbar",w); exit(10); }
225  k=strlen(kat[numk]+tgl+9)-strlen(kat[i]+tgl+9); //Laengenkorrektur**
226  j=tgl+2; while(j<9+tgl) { kat[numk][j]=kat[i][j]+k; ++j; }
227  j=j+strlen(kat[i]+j+1);
228  while(kat[i]+j<kat[i+1]) src[pos++]=kat[i][j++];
229  i=tgl+2; wi+=tgl+1; goto STRUCTURE;
230  // $M und $P koennten anders definiert sein **
231  }
232  */
233  if (numk==kdim) sprintf(Aerror,"too many field definitions");
234  else kat[++numk]=src+pos; // pos ist die Position hinter der letzten \0
235  if (!(numk%256))
236  {
237  kat[numk+1]=kat[numk];
238  kat[numk]=kat[numk-1];
239  ++numk; // avoid 256 and 512// $$951110
240  }
241  // jetzt ist kat[numk] die Adresse fuer den naechsten Deskriptor
242  }
243  break;
244  case 'a': // Befehle fuer externe Anwendungen, a=ALF
245  case 'b': // b=ORDER
246  // war nur bei DOS implementiert, Zeile uebergehen
247  break;
248  case 'c': /* cnkkk : #kkk to contain date entered
249  cemmm : #mmm date last edited
250  cglll : #lll generated number
251  cij : j = Index number for cg */
252  {
253  int i=tgl+1;
254  switch (*c1)
255  {
256  case 'n':
257  strncpy(dat_n,(char *)c1+1,i);
258  dat_n[i]=0;
259  break;
260  case 'e':
261  strncpy(dat_e,(char *)c1+1,i);
262  dat_e[i]=0;
263  break;
264  case 'g':
265  strncpy(dat_g,(char *)c1+1,i);
266  dat_g[i]=0;
267  break;
268  case 'i':
269  {
270  if (c1[1]<'1' || c1[1]>';')
271  sprintf(Aerror,"error in %s, digit expected behind ci",c1-1);
272  else strcpy(ind_g,c1+1);
273  break;
274  }
275  }
276  break;
277  }
278  case 'D': // len of date
279  DL=atoi(c1);
280  break;
281  case 'd': // disregardable words at start of field
282  strcat((char *)art,(char *)c1);
283  strcat((char *)art," ");
284  break;
285  case 'F': // filler character, def=219
286  FIL=(CHAR)atoi(c1);
287  break;
288  case 'f': // fillers
289  lz=atoi(c1);
290  break;
291  case 'K': // Kategory code, def=35
292  KC=(CHAR)atoi(c1);
293  break;
294  case 'k': // kat start position
295  skt=atoi(c1);
296  break;
297  case 'l': // language
298  c1[3]=NL;
299  strcpy(Alanguage,c1);
300  break;
301  case 'M': // Multcode
302  multcode=*c1;
303  break;
304  case 'm': // memory settings / m-Befehle f. Speicherbereiche
305  i=atoi(c1+1);
306  switch (*c1)
307  { // defaults:
308  case 'k': // mk: max# of fields
309  gdim=i;
310  break;
311  case 'K': // mK: gspace
312  gspace=i+10000;
313  break;
314  case 'd': // md: kdim , max# of descriptors
315  kdim=i;
316  break;
317  case 'b': // mb: fdim 200
318  f_dim=i+500;
319  break;
320  case 'B': // mB: fspace add 100000
321  fspace=i+100000;
322  break;
323  case 'P': // mP: pspace 4000
324  pspace+=i; // default 10000 mindestens!
325  break;
326  case 'X': // mX: parmem 40000
327  parmem=i;
328  break;
329  }
330  break;
331 
332  case 't': // tag length
333  if (numk>1)
334  {
335  strcpy(Aerror,uif[252]);
336  exit(10);
337  }
338  tgl=TGL=atoi(c1);
339  wi=cline+tgl+1; // Pos von "name" in w
340  break;
341 
342  case '': // subfield code, def=31
343  SF=(CHAR)atoi(c1);
344  break;
345  case 'n': // non-sort mode
346  nsm=*c1-'0'; // 0 : default, NSarticle
347  break; // 1 : NSarticleNS
348  case 'N': // non-sort char, def=170
349  NS=(CHAR)atoi(c1);
350  break;
351  case 'p': // printer name
352  strcpy(Aprinter,c1);
353  break;
354  case 'S': // non-stop char, def=64
355  NN=(CHAR)atoi(c1);
356  if (!NN) NN=64;
357  break;
358  case 'w': // window mode
359  break;
360  case 'Y':
361  JA=cline[1];
362  if (cline[2]!=' ' && cline[2]) NEIN=cline[2];
363  break;
364 
365  default: // alles andere sind Abfragezeilen!
366  if (qs==(CHAR*)NULL) // erste Abfragezeile gefunden: Deskriptoren zu ende
367  {
368  i=1; // CHAR *ka;
369  unsigned kl=kat[numk]-kat[1]+4; // soviel bytes umkopieren!
370  katlist=new CHAR [kl+2]; // $$960918 +2
371  memmove(katlist,Aspace,kl+1);
372  while (i<numk)
373  {
374  kat[i]=katlist+(kat[i]-Aspace);
375  ++i;
376  }
377 
378  qs=Aspace; // qs jetzt Adresse des Abfragelistenanfangs
379  *qs=0;
380  } // 1st prompt line
381 
382  else strcat(qs,"\377"); // delimiter 255
383  strcat(qs,cline); // Abfragezeilen hintereinander kopieren
384  break;
385  }
386  }
387  } // end while(fgets...)
388 
389  if (qs==(CHAR*)NULL) // es gab keine Abfrageliste
390  {
391  i=1; // CHAR *ka;
392  unsigned kl=kat[numk]-kat[1]+4; // soviel bytes umkopieren!
393  katlist= new CHAR[kl+2]; // $$960918 +2
394  memmove(katlist,Aspace,kl+1);
395  while (i<numk)
396  {
397  kat[i]=katlist+(kat[i]-Aspace);
398  ++i;
399  }
400  }
401  else // es gibt eine: umkopieren
402  {
403  qs=new CHAR[strlen(Aspace)+4];
404  strcpy(qs,Aspace); // kopiere Abfrageliste
405  }
406  *Aspace=0;
407 
408 // prepare the phrase space for global use
409  if (phr==(CHAR*)NULL)
410  {
411  phr= new CHAR [pspace];
412  if (!phr)
413  {
414  sprintf(Aerror,"phrase space: %d bytes is too much%s",pspace,0);
415  return;
416  }
417 
418  pa[0]=pend=phr;
419  pi[0]=phi=0;
420  }
421  fclose(cfgFile);
422 
423 // Abfrageliste ist ein einziger String (Trenner zw. Abfr. = 255)
424 // kann deshalb einfach umkopiert werden: (ist provisorisch auf qs=Aspace!)
425 
426  return;
427 }
428 
429 // -----------------------------------------------------------------
430 
431 // ****** METHODEN
432 
433 // ****** Label zu einer Feldnummer ermitteln
434 
435 int KONFIG::KoGetLabel(CHAR *ax,CHAR *wx) // ax="#20" ==> wx="Titel"
436 {
437  int i;
438  CHAR *k;
439  k=qs;
440  wx[0]=0;
441  if (k && ax[tgl+1]!=' ') // #xyz with z!=' '
442  while (1) // then check prompt list first
443  {
444  if (!strncmp(ax+1,(CHAR *)k,tgl+1))
445  {
446  i=0;
447  k+=tgl+2;
448  while (!isalnum(*k)) ++k;
449  while (*k && *k!=255) wx[i++]=*k++;
450 
451  wx[i--]=0;
452  if (wx[i-1]=='+') --i;
453  while (!isalnum(wx[i])) wx[i--]=0;
454  break;
455  }
456  while (*k && *k!=255) ++k;
457  if (!*k) break;
458  ++k;
459  }
460 
461  if (!*wx) // not found in prompts
462  {
463  i=KoVerify(ax);
464  if (i!=-1) strcpy(wx,kat[i]+tgl+9);
465  else return 0;
466  // wx="fieldname"
467  }
468  return 1;
469 }
470 
471 
472 
473 // ******* Verifiziere: Kategorienummer gueltig?
474 // -1: nein, sonst return-Wert = interne Nummer gemaess CFG
475 
476 int KONFIG::KoVerify(CHAR *adr) // is there a valid tag at adr ? %% DOS: ktest()
477 {
478  int i=3; // descriptors start at kat[1] !!!
479  if (*adr==KC) ++adr;
480  while (i<numk)
481  {
482  if (*kat[i]==*adr) if (!strncmp(kat[i],adr,tgl)) break;
483  ++i;
484  }
485  if (i==numk) // it was not valid
486  {
487  if (!strncmp(kat[1],adr,2)) return 1; // it's #u1
488  if (!strncmp(kat[2],adr,2)) return 2; // it's #u2
489  // $$980312 : .20s sonst evtl. zu lang
490  sprintf(Aerror,"%.20s ist keine gueltige Kategorie%c",adr,0);
491  return -1;
492  }
493  return i; // internal number
494 }
495 
496 
497 // ********* Kategorietext gemaess CFG validieren %% neditor.c kcheck()
498 // return: <1 bei Fehler
499 // kcc = interne Kat.Nr., d.h. kat[kcc] ist der Deskriptor
500 // ftext = Adresse des zu checkenden Feldtextes
501 // md=1 check for mandatory subf 0=skip that check
502 // ret: 1 = valid, 0 = invalid %% DOS: kcheck()
503 
504 int KONFIG::KoValidate(int kcc, CHAR *ftext, int md)
505 {
506  CHAR *adr, *wt, *allow, *check;
507  int i, j, v=1;
508  if (*Aerror==8) return 1; // FLEX: accept everything
509  *Aerror=0; // $$970616 NEU
510  wt=ftext;
511  if ((v=s_check(kcc,(char *)ftext))<=0) return v ; // external check, user programmable
512 
513  /* Wahrscheinlich unnoetig, sonst verlegen in RECORD
514  if(kcc>2 && kcc<9) // #0.. hierarchy check
515  {
516  if (!cri && kcc>3) v=0;
517  else if (kcc>3 && kcc<9)
518  { i=cri-1;
519  while (*ga[i]!=RS) --i;
520  h=ga[i][1]; // hierarchy code of preceding record
521  if (kcc>h+3) v=0;
522  }
523  if (!v)
524  { sprintf(Aerror,"%s%c",uif[13],0); return -1; } // " Hierarchiefehler!"
525  }
526  */
527  i=kat[kcc][tgl+4];
528  if (i) allow=kat[kcc]+i;
529  else allow=(CHAR*)NULL; // addr of allowed subf codes
530  i=kat[kcc][tgl+2];
531 
532  if (i) check=kat[kcc]+i;
533  else check=(CHAR *)nil; // addr of check codes
534  adr=wt+skt;
535  if ((j=kat[kcc][tgl+1])!=0) // fixed field pattern F is defined
536  {
537  CHAR c,p;
538  CHAR *pat;
539  int i=0;
540  v=EOF;
541  pat=kat[kcc]+j; // here's the pattern
542  while ((c=*adr++)!=NL)
543  {
544  if (!(p=*pat)) break; // pattern has ended, rest goes unchecked
545  switch (*pat++)
546  {
547  case 'N': // letter or digit
548  if (isdigit(c)) break;
549  case 'A': // letter or space
550  c=toupper(c);
551  if (c<'A' || c>'Z') if (c!=' ') v=i;
552  break;
553  case '#':
554  if (c==' ' || c=='-' || c=='+') break;
555  case '9': // digit
556  if (!isdigit(c)) v=i;
557  break;
558  case 'L': // 0 or 1
559  if (c!=' ' && c!='0' && c!='1') v=i;
560  break;
561  case 'X': // any character allowed here
562  break;
563  default: // only the pattern char is allowed
564  if (p!=c) v=i;
565  break;
566  }
567  if (v!=EOF) break;
568  ++i;
569  }
570  if (v>=0)
571  {
572  sprintf(Aerror,uif[57],v+1,adr-1); // "Fehler auf Position %d = %.50s"
573  return -1;
574  }
575  // END fixed field treatment
576  adr=wt+skt;
577  }
578  // variable field treatment:
579  {
580  int s=250;
581  CHAR subfs[250], *sf; // all subf codes collected here $$040912 1024
582  *subfs=NL;
583  sf=subfs;
584  v=1;
585  if (*check==' ') v=KoSubCheck(adr,' ',check);
586  if (v) while (*adr && s && *adr!=10) // Mehrere Felder auf einmal! Trennung ist 10
587  { // Codes nur einsammeln bis zum Ende des ersten
588  // Aber: die weiteren werden nicht gecheckt, jedenfalls so, wie das
589  // in a99 abgearbeitet wird (2012-04-26)
590  if (*adr++==SF)
591  {
592  if (*adr!=SF)
593  {
594  *sf++=*adr;
595  --s;
596  if (allow) if (!strchr(allow,*adr))
597  {
598  v=0;
599  break;
600  }
601  if (check) v=KoSubCheck(adr+1,*adr,check);
602  if (v<1) return v;
603  }
604  }
605  }
606  else return 0;
607  *sf=NL;
608  if (v<1)
609  {
610  if (!*Aerror) // $$970616 NEU
611  if(allow) sprintf(Aerror,uif[58],'$',*adr,allow); // "unerlaubtes Subf. %c%c, erlaubt sind %s"
612  return v;
613  }
614  if (md)
615  {
616  v=kat[kcc][tgl+5]; // mandatory subf
617  if (v)
618  {
619  sf=kat[kcc]+v;
620  v=0;
621  while (*sf) if (!strchr(subfs,*sf++)) v=sf[-1];
622  if (v)
623  {
624  sprintf(Aerror,uif[60],v); // "es fehlt Teilfeld %c"
625  return -1;
626  }
627  }
628  v=kat[kcc][tgl+6]; // repeatable subf
629  if (v)
630  {
631  int i=0;
632  sf=kat[kcc]+v;
633  v=0;
634  while (subfs[i]) if (strchr(subfs+i+1,subfs[i]))
635  if (!strchr(sf,subfs[i++])) v=i;
636  else ;
637  else ++i;
638  if (v)
639  {
640  sprintf(Aerror,uif[67],subfs[v-1]); // "Teilfeld %c nicht mehrfach erlaubt"
641  return -1;
642  }
643  }
644  // check for repeatable and mandatory subfs
645  }
646  if (skt-tgl>2) // do we have indicators?
647  {
648  v=kat[kcc][tgl+7];
649  if (v)
650  {
651  allow=kat[kcc]+v; // addr of allowed indic1 codes
652  v=wt[tgl+2]; // Korr. $$960304
653  }
654  else v=' ';
655  if (v!=' ' && allow[1] && !strchr(allow,v))
656  {
657  sprintf(Aerror,uif[68],wt[tgl+2],allow); // "falscher Indikator =%c, erlaubt: %s"
658  return -1;
659  }
660  if (skt-tgl==4) // if defined, check 2nd indic
661  {
662  v=kat[kcc][tgl+8]; // Korr. $$960304
663  if (v)
664  {
665  allow=kat[kcc]+v;
666  v=wt[tgl+3];
667  }
668  else v=' ';
669  if (v!=' ' && !strchr(allow,wt[tgl+3]))
670  {
671  sprintf(Aerror,uif[99],v,allow); // "falscher 2. Indikator =%c, erlaubt: %s"
672  return -1;
673  }
674  }
675  }
676  }
677  return 1;
678 } // end Validate()
679 
680 
681 // ***** Unterroutinen der Validierung
682 int KONFIG::KoSubCheck(CHAR *adr,CHAR c,CHAR *check)
683 // check string adr , subf c as directed by check
684 // return 0 : field faulty,
685 // -1 : it cannot be accepted
686 {
687  // $$970616 NEU : ec=1 sonst undefiniert!
688  int j, ec=1; // error code; goes <= 0 in case of error
689  int k,n,z0,z1,i;
690  if (*adr==SF) adr+=2;
691 
692  while (*check)
693  if (*check!=' ' && *check!=c) check+=2;
694  else
695  {
696  switch (*++check)
697  {
698  case 'c': // check for initial article
699  if (Apgnb=='1') KoArticle(adr);
700  break;
701 
702  case 'e': // #76 year ?
703  {
704  CHAR jj[24];
705  int y;
706  SyTime(jj);
707  jj[4]=0;
708  y=atoi(jj)+2;
709  while (!isdigit(*adr)) ++adr;
710  j=atoi(adr);
711  if (j<1450 || j>y)
712  {
713  sprintf(Aerror,"%s\n%s",adr,uif[15]); // " Jahreszahl richtig?"
714  ec=0;
715  }
716  break;
717  }
718 
719  case 'd': // Name (leider nur erster, wenn mehrere...)
720  if (*adr>127 || isalpha(*adr)) // Beginn mit Buchstabe? Sonst V14-Id., dann nicht pruefen
721  {
722  j=strlen(adr);
723  i=0;
724  while (adr[i++]!=',' && i<j) ;
725  if (adr[i]!=' ' || i==j)
726  {
727  sprintf(Aerror,"%s\n%s",adr,uif[14]); // " Kommafehler?"
728  ec=0;
729  }
730  }
731  break;
732 
733  case 'f': // #83 #85 semicolon?
734  j=strlen(adr);
735  i=0;
736  while (adr[i++]!=';' && i<j) ;
737  if ((adr[i]!=' ' || adr[i-2]!=' ') || i==j)
738  {
739  sprintf(Aerror,uif[16]); // " Semik.fehler?"
740  ec=0;
741  }
742  break;
743 
744  case 'g': // ISBN check
745  {
746  unsigned int z[14]; // for ISBN
747  k=0;
748  n=0;
749 
750  if(strlen(adr)>9) // weniger als 10 ist ISSN
751  {
752  while (adr[k])
753  {
754  // scan for 1st occurrence of -digit
755  while (adr[++k]!='-' && k<strlen(adr)) ;
756  if (!isdigit(adr[k+1]))
757  {
758  ++k;
759  continue;
760  }
761 /* if (k==strlen(adr))
762  {
763  sprintf(Aerror,uif[20]);
764  ec=0;
765  break;
766  }
767  */
768  while (isdigit(adr[--k]) && k>-1) ;
769  ++k; // back to 1st digit
770  j=0;
771 // $$060622: new ISBN 13digit 978-...
772 
773  if (adr[k]=='9' && adr[k+1]=='7' && adr[k+3]=='-')
774  {
775  while (j<13 && adr[k]!=NL)
776  {
777  if (isdigit(adr[k])!=0)
778  {
779  z[j]=adr[k]-'0';
780  ++j;
781  }
782  ++k;
783  }
784  if (adr[k]==NL && j<12)
785  {
786  sprintf(Aerror,uif[20]);
787  ec=0;
788  break;
789  }
790  ++n;
791  z0=z[0]+z[1]*3+z[2]+z[3]*3+z[4]+z[5]*3+z[6]+z[7]*3+z[8]+z[9]*3+z[10]+z[11]*3;
792  z1=10-z0%10;
793  if (z1==10) z1=0;
794  if (z1!=z[12])
795  {
796  z1=z1+'0';
797  sprintf(Aerror,uif[17],z1,z[12]); // ISBN-Pruefziffer falsch, Vorlage falsch?
798  i=strlen(adr)+2;
799  while (i>=k)
800  {
801  adr[i]=adr[i-1];
802  i--;
803  }
804  adr[k]='*';
805  ++k;
806  ec=0;
807  }
808  }
809  else // 10 Ziffern
810  {
811  while (j<10 && adr[k]!=NL)
812  {
813  if (isdigit(adr[k]) || (adr[k]|32)=='x')
814  {
815  if((adr[k]|32)=='x') z[j]=10; else z[j]=adr[k]-'0';
816  ++j;
817  }
818  ++k;
819  }
820 /*
821  if (adr[k]==NL && j<10)
822  {
823  sprintf(Aerror,uif[20]);
824  ec=0;
825  break;
826  }
827 */
828  ++n;
829 // if ((adr[k-1]|32)=='x'-'0') z[9]=10;
830  z0=z[0]*10+z[1]*9+z[2]*8+z[3]*7+z[4]*6+z[5]*5+z[6]*4+z[7]*3+z[8]*2;
831  z1=11-z0%11;
832  if (z1==11) z1=0;
833  if (z1!=z[9])
834  {
835  if(z1==10) z1='X'; else z1=z1+'0';
836  sprintf(Aerror,uif[17],z1,z[9]); // ISBN-Pruefziffer falsch, Vorlage falsch?
837  i=strlen(adr)+2;
838  while (i>=k)
839  {
840  adr[i]=adr[i-1];
841  i--;
842  }
843  adr[k]='*';
844  ++k;
845  ec=0;
846  }
847  }
848  }
849  break;
850  } // fallthru for ISSN
851  }
852 
853  case 'h': // ISSN check
854  {
855  unsigned int z[8]; // for ISSN
856  k=0;
857  n=0;
858  while (adr[k] && adr[k]!='-') ++k; // is there a hyphen?
859  k-=4;
860  if (isdigit(adr[k]) && adr[k+4]=='-')
861  while (adr[k])
862  {
863  // scan for -digit
864  while (adr[++k]!='-' && k<strlen(adr)) ;
865  if (!isdigit(adr[k+1]))
866  {
867  ++k;
868  continue;
869  }
870  if (k==strlen(adr))
871  {
872  sprintf(Aerror,uif[20]); // ISBN/ISSN-Fehler
873  ec=0;
874  break;
875  }
876  while (isdigit(adr[--k]) && k>-1) ;
877  ++k;
878  j=0;
879  while (j<8 && adr[k]!=NL)
880  {
881  if (isdigit(adr[k])!=0 || (adr[k]|32)=='x')
882  {
883  z[j]=adr[k]-'0';
884  ++j;
885  }
886  ++k;
887  }
888  if (adr[k]==NL && j<7)
889  {
890  sprintf(Aerror,uif[20]);
891  ec=0;
892  break;
893  }
894  ++n;
895  if ((adr[k-1]|32)=='x') z[7]=10;
896  z0=z[0]*8+z[1]*7+z[2]*6+z[3]*5+z[4]*4+z[5]*3+z[6]*2;
897  z1=11-z0%11;
898  if (z1==11) z1=0;
899  if (z1!=z[7])
900  {
901  if(z1==10) z1='X'; else z1=z1+'0';
902  sprintf(Aerror,uif[19], z1, z[7]); // " ISSN-Pruefziffer falsch, Vorlage falsch?"
903  i=strlen(adr)+2;
904  while (i>=k)
905  {
906  adr[i]=adr[i-1];
907  i--;
908  }
909  adr[k]='*';
910  ++k;
911  ec=0;
912  }
913  }
914  }
915  break;
916 
917 
918  case 't': // Datum in der Form yyyy.mm.dd?
919  {
920  int k=0;
921  if (adr[skt+4]!='.' || adr[skt+7]!='.') k=1;
922  j=atoi(adr+skt);
923  if (j<1000 || j>2999) k=1;
924  j=atoi(adr+skt+5);
925  if (j<1 || j>12) k=1;
926  j=atoi(adr+skt+8);
927  if (j<1 || j>31) k=1;
928  if (k)
929  {
930  sprintf(Aerror,"%s\n%s",adr,uif[27]); // " Jahreszahl richtig?"
931  ec=0;
932  break;
933  }
934  }
935  default: // no check required, includes 'a'
936  break;
937  }
938  ++check;
939  if (ec<=0) break;
940  }
941  return ec;
942 } // end Subcheck()
943 
944 
945 // ********** Artikelpruefung
946 int KONFIG::KoArticle(CHAR *adr) // does adr begin with an article ?
947 // return: 0:no, 1:nsm=0, 2:nsm=1 4:nsm=4
948 {
949  int i, j, j0, k;
950  i=0;
951  j0=k=0;
952  if (adr[k]==NS) return 0;
953  while (!isalpha((int)adr[k]) && adr[k]) ++k;
954  if (!adr[k]) return 0;
955  if (adr[k-1]==' ')
956  {
957  adr+=k;
958  k=j0=0;
959  }
960  j=k;
961 c_strt:
962  if (!isalnum(art[i])) return 0;
963  while (tolower((int)adr[k])==art[i])
964  {
965  ++i;
966  if (adr[k]==' ') goto c_fnd;
967  ++k;
968  }
969  if (strchr(" -'",adr[k])!=NULL && art[i]==' ') goto c_fnd;
970  while (isalnum(art[i])) ++i;
971  ++i;
972  k=j;
973  goto c_strt;
974 c_fnd:
975  if (Apgnb=='1') // " Ist das erste Wort ein Ordnungswort?"
976  {
977  j=strlen(adr)+1;
978  i=1;
979  sprintf(Aerror,"%s%c",uif[21],0); // ordnWort? $$970616 NEU
980  if (nsm==4) // MARC mode
981  {
982  while (adr[i++]!=' ') ;
983  adr[skt-1]=i+'0'; // 2. Indikator, Ziffer einsetzen
984  return 4;
985  }
986  while (j>j0)
987  {
988  adr[j]=adr[j-1];
989  --j;
990  }
991  adr[j0]=NS;
992  if (nsm) // non-sort mode 1: _..._
993  {
994  i=2;
995  j=j0;
996  while (strchr(" -'",adr[++k])==NULL);
997  j=strlen(adr)+1;
998  while (j>k)
999  {
1000  adr[j]=adr[j-1];
1001  --j;
1002  }
1003  adr[k]=NS;
1004  }
1005  }
1006  return i;
1007 }
1008 
1009 
1010 // ***** Destruktor
1011 
1013 {
1014  if (kat)delete [] kat;
1015  kat=(CHAR**)NULL;
1016  if (katlist)delete [] katlist;
1017  katlist=(CHAR*)NULL;
1018  if (qs)delete [] qs;
1019  qs=(CHAR*)NULL;
1020  if (Aspace) delete [] Aspace;
1021  Aspace=0; //$$030218
1022  return;
1023 }
1024 
1025 /*
1026  Copyright 2011 Universitätsbibliothek Braunschweig
1027 
1028  Licensed under the Apache License, Version 2.0 (the "License");
1029  you may not use this file except in compliance with the License.
1030  You may obtain a copy of the License at
1031 
1032  http://www.apache.org/licenses/LICENSE-2.0
1033 
1034  Unless required by applicable law or agreed to in writing, software
1035  distributed under the License is distributed on an "AS IS" BASIS,
1036  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1037  See the License for the specific language governing permissions and
1038  limitations under the License.
1039 */
1040