Back to index

lightning-sunbird  0.9+nobinonly
spf2ldiff.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 
00040 #include "rdf-int.h"
00041 
00042 char* error_string = NULL;
00043 int lineNumber = 0;
00044 void
00045 main (int argc, char* argv[]) {
00046   RDFFile rf = initFileStruct();
00047   int ok = 1;
00048   error_string = getMem(1000);
00049   if (argc == 2) {
00050     FILE* f = fopen(argv[1], "r");
00051     if (f != NULL) {
00052       char* buff = getMem(RDF_BUF_SIZE);
00053          int len;
00054       while (ok && ((len = fread(buff, 1, RDF_BUF_SIZE-1, f)) > 0)) {
00055         buff[len] = '\0';
00056         ok = parseNextRDFXMLBlobInt(rf,  buff, strlen(buff));    
00057         memset(buff, '\0', RDF_BUF_SIZE);
00058       }
00059     }
00060     if (ok) {
00061       while (1) {
00062         char* nextQuery = getMem(200);
00063         int n;
00064         nextQuery = gets(nextQuery);
00065         if (nextQuery) {
00066           char** ans = processRDFQuery(nextQuery);
00067           if (ans) {
00068             for (n = 0; ans[n] != NULL; n++) {
00069               printf("%s\n", ans[n]);
00070             }
00071           }
00072         } else {
00073           break;
00074         }
00075       }
00076     }    
00077   }
00078 }
00079 
00080 void 
00081 RDF_Init () {
00082   error_string = getMem(1000);
00083 }
00084 
00085 int
00086 RDF_DigestNewStuff (char* fileName, char* data, int len) {
00087   RDFFile rf = initFileStruct();
00088   int ok = 1;
00089   ok = parseNextRDFXMLBlobInt(rf, data, len);    
00090   freeMem(rf->line);
00091   freeMem(rf->holdOver);
00092   return ok;
00093 }
00094   
00095 
00096 RDFFile
00097 initFileStruct (void) {
00098   RDFFile ans = (RDFFile)getMem(sizeof(RDF_FileStruct));
00099   ans->line = (char*)getMem(RDF_BUF_SIZE);
00100   ans->holdOver = (char*)getMem(RDF_BUF_SIZE);
00101   ans->depth = 1;
00102   ans->lastItem = ans->stack[0] ;
00103   return ans;
00104 }
00105 
00106 
00107 PRBool
00108 startsWith (const char* pattern, const char* uuid)
00109 {
00110   int l1 = strlen(pattern);
00111   int l2 = strlen(uuid);
00112   int n;
00113   if (l2 < l1) return 0;
00114   for (n = 0; n < l1; n++) {
00115     if (pattern[n] != uuid[n]) return 0;
00116   } 
00117   return 1;
00118 }
00119 
00120 char* 
00121 getMem (size_t n) {
00122   return (char*) calloc(1, n);
00123 }
00124 
00125 void 
00126 freeMem(void* item) {
00127   free(item);
00128 }
00129 
00130 char 
00131 decodeEntityRef (char* string, int* stringIndexPtr, int len) {
00132   if (startsWith("lt;", string)) {
00133     *stringIndexPtr = *stringIndexPtr + 3;
00134     return '<';
00135   } else if (startsWith("gt;", string)) {
00136     *stringIndexPtr = *stringIndexPtr + 3;
00137     return '>';
00138   } else  if (startsWith("amp;", string)) {
00139     *stringIndexPtr = *stringIndexPtr + 4;
00140     return '&';
00141   } else return '&';
00142 }
00143 
00144 char *
00145 copyStringIgnoreWhiteSpace(char* string)
00146 {
00147    int len = strlen(string);
00148    char* buf = (char*)getMem(len + 1);
00149    PRBool inWhiteSpace = 1;
00150    int buffIndex = 0;
00151    int stringIndex = 0;
00152 
00153    while (stringIndex < len) {
00154      char nextChar = *(string + stringIndex);
00155      PRBool wsp = wsCharp(nextChar);
00156      if (!wsp) {
00157        if (nextChar == '&') {
00158          *(buf + buffIndex++) = decodeEntityRef(&string[stringIndex+1], 
00159                                                 &stringIndex, len-stringIndex);
00160        } else {
00161          *(buf + buffIndex++) = nextChar;
00162        }
00163        inWhiteSpace = 0;
00164      } else if (!inWhiteSpace) {
00165        *(buf + buffIndex++) = ' ';
00166        inWhiteSpace = 1;
00167      } else {
00168        inWhiteSpace = 1;
00169      }
00170      stringIndex++;
00171    }
00172 
00173    return buf;
00174 }
00175 
00176 char *
00177 getHref(char** attlist)
00178 {
00179        char* ans = getAttributeValue(attlist, "resource");
00180        if (!ans) ans = getAttributeValue(attlist, "rdf:resource");
00181        return ans;
00182 }
00183 
00184 
00185 char *
00186 getID(char** attlist)
00187 {
00188        char* ans = getAttributeValue(attlist, "id");
00189        if (!ans) ans = getAttributeValue(attlist, "about"); 
00190        if (!ans) ans = getAttributeValue(attlist, "rdf:about");
00191        return ans;
00192 }
00193  
00194 
00195 int 
00196 parseNextRDFXMLBlobInt(RDFFile f, char* blob, int size) {
00197   int n, last, m;
00198   PRBool somethingseenp = 0;
00199   n = last = 0; 
00200   while (n < size) {
00201     char c = blob[n];
00202     if ((c == '\n') || (c == '\r')) lineNumber++;
00203     m = 0;
00204     somethingseenp = 0;
00205     memset(f->line, '\0', RDF_BUF_SIZE-1);
00206     if (f->holdOver[0] != '\0') {
00207       memcpy(f->line, f->holdOver, strlen(f->holdOver));
00208       m = strlen(f->holdOver);
00209       somethingseenp = 1;
00210       memset(f->holdOver, '\0', RDF_BUF_SIZE-1);
00211     }   
00212     while ((n < size) && (wsCharp(c))) {
00213       c = blob[++n]; 
00214       if ((c == '\n') || (c == '\r')) lineNumber++;
00215     }
00216     while ((m < RDF_BUF_SIZE) && (c != '<') && (c != '>')) {
00217       f->line[m] = c;
00218       m++;
00219       somethingseenp = (somethingseenp || (!(wsCharp(c))));
00220       n++;    
00221       if (n < size) c = blob[n]; 
00222       else break;
00223       if ((c == '\n') || (c == '\r')) lineNumber++;
00224     }
00225     if (c == '>') f->line[m] = c;
00226     n++;
00227     if (m > 0) {
00228       if ((c == '<') || (c == '>')) {
00229         last = n;
00230         if (c == '<') f->holdOver[0] = '<'; 
00231         if (somethingseenp == 1) {
00232           int ok = parseNextRDFToken(f, f->line);
00233           if (!ok) 
00234                        return 0;
00235         }
00236       } else if (size > last) {
00237         memcpy(f->holdOver, f->line, m);
00238       }
00239     } else if (c == '<') f->holdOver[0] = '<';
00240   }
00241   return(1);
00242 }
00243 
00244 char *
00245 getAttributeValue (char** attlist, char* elName)
00246 {
00247   size_t n = 0;
00248   if (!attlist) return NULL;
00249   while ((n < 2*MAX_ATTRIBUTES) && (*(attlist + n) != NULL)) {
00250     if (strcmp(*(attlist + n), elName) == 0) return *(attlist + n + 1);
00251     n = n + 2;
00252   }
00253   return NULL;
00254 }
00255 
00256 char* 
00257 copyString (char* str) {
00258   char* ans = getMem(strlen(str)+1);
00259   if (ans) {
00260     memcpy(ans, str, strlen(str));
00261     return ans;
00262   } else return NULL;
00263 }
00264 
00265 void
00266 addElementProps (char** attlist, char* elementName, RDFFile f, RDF_Resource obj)
00267 {
00268   int count = 0;
00269   while (count < 2*MAX_ATTRIBUTES) {
00270     char* attName = attlist[count++];
00271     char* attValue = attlist[count++];
00272     if ((attName == NULL) || (attValue == NULL)) break;
00273     if (!stringEquals(attName, "resource") && 
00274         !stringEquals(attName, "rdf:resource")  && 
00275         !stringEquals(attName, "about") && 
00276         !stringEquals(attName, "rdf:about") && 
00277         !stringEquals(attName, "tv") &&
00278         !stringEquals(attName, "id")) {
00279       remoteStoreAdd(f, obj, getResource(f, attName), 
00280                    copyStringIgnoreWhiteSpace(attValue), 
00281                    RDF_STRING_TYPE, 1);
00282     }
00283   }
00284 }
00285         
00286 int
00287 parseNextRDFToken (RDFFile f, char* token)
00288 {
00289   char* attlist[2*MAX_ATTRIBUTES+1];
00290   char* elementName;
00291   if (token[0] == '<') {
00292     size_t len = strlen(token);
00293     if (token[len-2] != '/') {
00294       if (token[1] == '/') {
00295         char* tok = getMem(len);
00296         memcpy(tok, &token[2], len-3);
00297         if (!stringEquals(tok, f->tagStack[f->tagDepth-1])) {
00298           sprintf(error_string, "Unbalanced tags : Expecting </%s>, found %s", 
00299                   f->tagStack[f->tagDepth-1], token);
00300           return 0;
00301         } else {
00302           f->tagDepth--;
00303           freeMem(tok);
00304         }
00305       } 
00306     }
00307   }
00308         
00309   if (token[0] != '<')   {
00310     if ((f->status == EXPECTING_OBJECT) && (f->depth > 1)) {
00311       RDF_Resource u = f->stack[f->depth-2];
00312       RDF_Resource s = f->stack[f->depth-1];
00313       char* val      = copyStringIgnoreWhiteSpace(token);
00314       remoteStoreAdd(f, u, s, val , RDF_STRING_TYPE, 1);
00315     } else  {
00316       sprintf(error_string, "Did not expect \n\"%s\".\n Was expecting a tag.", token);
00317       return 0;
00318     } 
00319   } else if  (startsWith("<!--", token)) {
00320     return 1;
00321   } else if (token[1] == '?')  {
00322     return 1;
00323   } else if (token[1] == '/') {
00324     if ((f->status != EXPECTING_OBJECT) && (f->status != EXPECTING_PROPERTY)) {
00325       sprintf(error_string, "Did not expect %s. Something pretty screwed up", token);
00326       return 0;
00327     }
00328     if (f->depth > 0) f->depth--;
00329     f->status = (f->status == EXPECTING_OBJECT ? EXPECTING_PROPERTY : EXPECTING_OBJECT);
00330     return 1;
00331   } else if ((f->status == 0) && (startsWith("<RDF:RDF", token) || 
00332                                   startsWith("<RDF>", token))) {
00333     f->tagStack[f->tagDepth++] = copyString("RDF"); 
00334     f->status = EXPECTING_OBJECT;
00335     return 1;
00336   } else {
00337     PRBool emptyElementp = (token[strlen(token)-2] == '/');  
00338     if ((f->status != EXPECTING_OBJECT) && (f->status != EXPECTING_PROPERTY)) return 1;
00339     if (!tokenizeElement(token, attlist, &elementName)) return 0;
00340     if (!emptyElementp) 
00341               f->tagStack[f->tagDepth++] = copyString(elementName);
00342     if (f->status == EXPECTING_OBJECT) {
00343       char* url = NULL;
00344       RDF_Resource obj;
00345       int count = 0;    
00346       url = getID(attlist);
00347       if (!url) {
00348         if (f->tagDepth > 2) {
00349           sprintf(error_string, "Unbalanced tags : Expecting </%s>, found %s", 
00350                   f->tagStack[f->tagDepth-2], token);
00351         } else {
00352           sprintf(error_string, "Require a \"about\" attribute on %s", token);
00353         }
00354         return 0;
00355       }
00356       obj =  getResource(f, url);
00357       addElementProps (attlist, elementName, f, obj) ;
00358       if (!stringEquals(elementName, "RDF:Description")) {
00359           RDF_Resource eln = getResource(f, elementName);
00360           remoteStoreAdd(f, obj, getResource(NULL, "instanceOf"), 
00361                        eln, RDF_RESOURCE_TYPE, 
00362                        1);        
00363       }
00364       if (f->depth > 1) {
00365         remoteStoreAdd(f, f->stack[f->depth-2], f->stack[f->depth-1], obj, 
00366                      RDF_RESOURCE_TYPE, 1);
00367       }
00368       if (!emptyElementp) {
00369         f->stack[f->depth++] = obj;
00370         f->status = EXPECTING_PROPERTY;
00371       }
00372     } else if (f->status == EXPECTING_PROPERTY) {
00373       char* url;
00374       RDF_Resource obj;
00375       int count = 0;
00376       url = getHref(attlist) ;      
00377       if (url) {
00378         RDF_Resource eln = getResource(f, elementName);
00379         char* tvAtt = getAttributeValue(attlist, "tv");
00380         obj =  getResource(f, url);        
00381         freeMem(url);
00382         addElementProps (attlist, elementName, f, obj) ;     
00383         remoteStoreAdd(f, f->stack[f->depth-1], eln, obj, RDF_RESOURCE_TYPE,  1);
00384                      
00385       } 
00386       if (!emptyElementp) {
00387         f->stack[f->depth++] = getResource(f, elementName);
00388         f->status = EXPECTING_OBJECT;
00389       }
00390     }
00391   }
00392 }      
00393 
00394 
00395 
00396 int
00397 tokenizeElement (char* attr, char** attlist, char** elementName)
00398 {
00399   size_t n = 1;
00400   size_t s = strlen(attr); 
00401   char c ;
00402   size_t m = 0;
00403   size_t atc = 0;
00404   PRBool emptyTagp =  (attr[s-2] == '/');
00405   PRBool inAttrNamep = 1;
00406   c = attr[n++]; 
00407   while (wsCharp(c)) {
00408     c = attr[n++];
00409   }
00410   *elementName = &attr[n-1];
00411   while (n < s) {
00412     if (wsCharp(c)) break;
00413     c = attr[n++];
00414   }
00415   attr[n-1] = '\0';
00416   while (atc < 2*MAX_ATTRIBUTES+1) {*(attlist + atc++) = NULL;}
00417   atc = 0;
00418   s = (emptyTagp ? s-2 : s-1);
00419   while (n < s) {
00420     PRBool attributeOpenStringSeenp = 0;
00421     m = 0;
00422     c = attr[n++];
00423     while ((n <= s) && (atc < 2*MAX_ATTRIBUTES)) {
00424       if (inAttrNamep && (m > 0) && (wsCharp(c) || (c == '='))) {
00425        attr[n-1] = '\0';
00426        *(attlist + atc++) = &attr[n-m-1];
00427        break;
00428       }
00429       if  (!inAttrNamep && attributeOpenStringSeenp && (c == '"')) {
00430        attr[n-1] = '\0';
00431        *(attlist + atc++) = &attr[n-m-1];
00432        break;
00433       }
00434       if (inAttrNamep) {
00435        if ((m > 0) || (!wsCharp(c))) m++;
00436       } else {
00437        if (c == '"') {
00438          attributeOpenStringSeenp = 1;
00439        } else {
00440          if ((m > 0) || (!(wsCharp(c)))) m++;
00441        }
00442       }
00443       c = attr[n++];
00444     }
00445     inAttrNamep = (inAttrNamep ? 0 : 1);
00446   }
00447   return 1;
00448 }