home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / db3.6-beta-src / dbparser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-26  |  30.0 KB  |  859 lines

  1. /* dbparser.c, -an RFFparser for db */
  2.  
  3. #include <exec/lists.h>
  4. #include <exec/types.h>
  5. #include <exec/memory.h>
  6. #include <proto/exec.h>
  7. #include <proto/utility.h>
  8. #include <proto/dos.h>
  9. #include <clib/alib_protos.h>           /* NewList() */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <dos.h>
  14.  
  15.  
  16. #include "db.h"
  17. #include "dbparser.h"
  18. #include "dbGUI.h"
  19. #include "dbRexx.h"     /* Only for the handling of the RXPORTNAME tag */
  20.  
  21. #define BUFSIZE 65536
  22.  
  23. #define Rewind(fp) Seek(fp, 0, OFFSET_BEGINNING)
  24.  
  25. char *RFFTagNames[] = {
  26.         "dummy",
  27.         "@RFF",
  28.         "TYPE",
  29.         "FLEN",
  30.         "LNAM",
  31.         "NAME",
  32.         "SIZE",
  33.         "OFFS",
  34.         "NEXT",
  35.         "TABSIZE",
  36.         "RXFILE",
  37.         "RXSTRING",
  38.         "AUTORXFILE",
  39.         "AUTORXSTRING",
  40.         "NEWRECORDRXFILE",
  41.         "NEWRECORDRXSTRING",
  42.         "FTYP",
  43.         "CENT",
  44.         "SFMT",
  45.         "RXPORTNAME",
  46.         "PLACE",
  47.         "ROWS",
  48.         "XPOS",
  49.         "YPOS",
  50.         NULL
  51. };
  52.  
  53. BPTR InFile;
  54.  
  55. void DeleteTag(struct RFFTag *ot)
  56. {
  57.         if (ot) {
  58.                 if (ot->Name) FreeMem(ot->Name,strlen(ot->Name)+1);
  59.                 if (ot->Data) FreeMem(ot->Data,strlen(ot->Data)+1);
  60.                 FreeMem(ot,sizeof(struct RFFTag));
  61.         }
  62. }
  63.  
  64. void DeleteRFFLine(struct RFFLine *ol)
  65. {
  66.         if (ol) {
  67.                 if (ol->Line) FreeMem(ol->Line,strlen(ol->Line)+1);
  68.                 FreeMem(ol,sizeof(struct RFFLine));
  69.         }
  70. }
  71.  
  72. struct RFFLine *NewRFFLine(const char *line)
  73. {
  74.         /* holds unknown RFF lines */
  75.         struct RFFLine *nl;
  76.  
  77.         if (!(nl = AllocMem(sizeof(struct RFFLine),0))) return NULL;
  78.         if (!(nl->Line = AllocMem(strlen(line)+1,0))) {
  79.                 DeleteRFFLine(nl);
  80.                 return NULL;
  81.         }
  82.         nl->mln.mln_Pred = NULL;
  83.         nl->mln.mln_Succ = NULL;
  84.         strcpy(nl->Line,line);
  85.  
  86.         return nl;
  87. }
  88.  
  89. struct RFFTag *NewTag(const char *name, int nlen, const char *data, int dlen)
  90. {
  91.         struct RFFTag *nt;
  92.         int i;
  93.  
  94.         if (!(nt = AllocMem(sizeof(struct RFFTag),MEMF_CLEAR))) return NULL;
  95.         if (!(nt->Name = AllocMem(nlen+1,0))) {
  96.                 DeleteTag(nt);
  97.                 return NULL;
  98.         }
  99.         if (!(nt->Data = AllocMem(dlen+1,0))) {
  100.                 DeleteTag(nt);
  101.                 return NULL;
  102.         }
  103.  
  104.         stccpy(nt->Name,name,nlen+1);
  105.         stccpy(nt->Data,data,dlen+1);
  106.         nt->ID = UNKNOWN;
  107.  
  108.         for(i=1; RFFTagNames[i]; i++)
  109.                 if (!Stricmp((STRPTR)nt->Name,(STRPTR)RFFTagNames[i])) {
  110.                         nt->ID = i;
  111.                         break;
  112.                 }
  113.         return nt;
  114. }
  115.  
  116.  
  117. struct FldInfo *NewFldInfo(void)
  118. {
  119.         /* Allocates and initializes a FldInfo struct with default values */
  120.         struct FldInfo *f;
  121.  
  122.         if (!(f = AllocMem(sizeof(struct FldInfo),0))) return NULL;
  123.         NewList((struct List *)&f->FldTags);
  124.         f->Next = NULL;
  125.         f->Len = DEFMAXFLDLEN;
  126.         /* f->Type = something */
  127.         return f;
  128. }
  129.  
  130. /* // Nice, but later on maybe. See DeletePro()
  131. void DeleteRxInfo(struct RxInfo *ri)
  132. {
  133.         struct RFFTag *ot;
  134.         while (ot = (struct RFFTag *)RemHead((struct List *)&ri->RxTags))
  135.                 DeleteTag(ot);
  136.         FreeMem(ri, sizeof(struct RxInfo));
  137. }
  138. */
  139.  
  140. struct RxInfo *NewRxInfo(void)
  141. {
  142.         /* Allocates and initializes an RxInfo struct with default values */
  143.         struct RxInfo *ri;
  144.  
  145.         if (ri = AllocMem(sizeof(struct RxInfo),0)) {
  146.                 NewList((struct List *)&ri->RxTags);
  147.                 ri->Next = NULL;
  148.         }
  149.         return ri;
  150. }
  151.  
  152. void DeleteVisFldInfo(struct VisFldInfo *vf)
  153. {
  154.         struct RFFTag *ot;
  155.         if (!vf) return;
  156.         if (vf->CEnt) FreeMem(vf->CEnt, (vf->NEnt+1)*sizeof(char *));
  157.  
  158.         while (ot = (struct RFFTag *)RemHead((struct List *)&vf->VisTags))
  159.                 DeleteTag(ot);
  160.         FreeMem(vf, sizeof(struct VisFldInfo));
  161. }
  162.  
  163. struct VisFldInfo *NewVisFldInfo(void)
  164. {
  165.         /* Allocates and initializes a VisFldInfo struct with default values */
  166.         struct VisFldInfo *vf;
  167.         struct IntuiText label = { 1,0,JAM1,0,0,NULL,NULL,NULL };
  168.         
  169.         if (!(vf = AllocMem(sizeof(struct VisFldInfo),0))) return NULL;
  170.         
  171.         NewList((struct List *)&vf->VisTags);
  172.         vf->Next = NULL;
  173.         vf->Gadget = NULL;
  174.         vf->Name[0] = '\0';
  175.         vf->Offset = 0;
  176.         vf->VisLen = 25;
  177.         vf->VisSep = '\n';
  178.         vf->FTyp = _STRING;
  179.         vf->Code = 0;
  180.         vf->CEnt = NULL;
  181.         vf->NEnt = 0;
  182.         
  183.         vf->Label = label;
  184.         vf->Label.IText = vf->Name;
  185.  
  186.         return vf;
  187. }
  188.  
  189. /* Support functions for RFFOut */
  190. struct RFFTag *FirstTag(struct MinList *list)
  191. {
  192.         struct RFFTag *tag = (struct RFFTag *)list->mlh_Head;
  193.         if (!tag->mln.mln_Succ) return NULL;    /* The MinList node */
  194.         return tag;
  195. }
  196.  
  197. struct RFFTag *NextTag(struct RFFTag *tag)
  198. {
  199.         tag = (struct RFFTag *)tag->mln.mln_Succ;
  200.         if (!tag->mln.mln_Succ) return NULL;    /* The MinList node */
  201.         return tag;
  202. }
  203.  
  204. struct RFFTag *NextSameTag(struct RFFTag *tag)
  205. {
  206.         short int oldID = tag->ID;
  207.  
  208.         for (;;) {
  209.                 tag = (struct RFFTag *)tag->mln.mln_Succ;
  210.                 if (!tag->mln.mln_Succ) return NULL;    /* The MinList node */
  211.                 if (tag->ID == oldID) return tag;
  212.         }
  213. }
  214.  
  215. struct VisFldInfo *CopyVisFldInfo(struct VisFldInfo *vf)
  216. {
  217.         struct RFFTag *tag, *nt;
  218.         struct VisFldInfo *newvf;
  219.         int i;
  220.  
  221.         if (!(newvf = NewVisFldInfo())) return NULL;
  222.  
  223.         *newvf = *vf;   /* Shallow copy. We have to do more than that */
  224.         newvf->Label.IText = newvf->Name;
  225.  
  226.         NewList((struct List *)&newvf->VisTags);
  227.         newvf->CEnt = NULL;
  228.  
  229.         for (tag = FirstTag(&vf->VisTags); tag; tag = NextTag(tag)) {
  230.                 if (!(nt = NewTag(tag->Name, strlen(tag->Name), tag->Data, strlen(tag->Data)))) {
  231.                         DeleteVisFldInfo(newvf);
  232.                         return NULL;
  233.                 }
  234.                 else AddTail((struct List *)&newvf->VisTags, (struct Node *)nt);
  235.         }
  236.  
  237.         if (tag = SearchTag(CurrentPro, newvf, NULL, CENT)) {
  238.                 if (!(newvf->CEnt =
  239.                  AllocMem((vf->NEnt+1)*sizeof(char *), 0)))
  240.                         {
  241.                                 DeleteVisFldInfo(newvf);
  242.                                 return NULL;
  243.                         }
  244.                 for (i=0; tag ;i++, tag = NextSameTag(tag))
  245.                         newvf->CEnt[i] = tag->Data;
  246.                 newvf->CEnt[i] = NULL;  /* Nullterm cycleentrylist */
  247.         }
  248.         return newvf;
  249. }
  250.  
  251.  
  252. struct RFFTag *CreateAndAddTag(struct MinList *list, short int id, char *newdata)
  253. {
  254.         struct RFFTag *tag;
  255.  
  256.         if (!(tag = NewTag(RFFTagNames[id], strlen(RFFTagNames[id]),
  257.                                                          newdata, strlen(newdata)))) return NULL;
  258.         AddTail((struct List *)list, (struct Node *)tag);
  259.         return tag;
  260. }
  261.  
  262.  
  263. struct RFFTag *UpdateTag(struct MinList *list, short int id, char *newdata)
  264. {
  265.         /* Updates tag with ID=id in RFFTaglist list. Creates tag if missing */
  266.         /* Returns updated tag or NULL if memory error */
  267.  
  268.         struct RFFTag *tag;
  269.  
  270.         if (!(tag = FindTag(list, id))) {                        /* Create new tag */
  271.                 if (!(tag = NewTag(RFFTagNames[id], strlen(RFFTagNames[id]),
  272.                                                                  newdata, strlen(newdata)))) return NULL;
  273.                 AddTail((struct List *)list, (struct Node *)tag);
  274.         }
  275.         else {  /* old tag found */
  276.                 int dlen = strlen(newdata);
  277.                 char *to;
  278.                 if (!(to = AllocMem(dlen+1,0))) return NULL;
  279.                 if (tag->Data) FreeMem(tag->Data,strlen(tag->Data)+1);
  280.                 tag->Data = to;
  281.                 stccpy(tag->Data,newdata,dlen+1);
  282.         }
  283.         return tag;
  284. }
  285.  
  286. void WriteVisTags(struct VisFldInfo *vf)
  287. {
  288.         /* Copy information from vf to vf's tags */
  289.         /* i.e. write vf's Name, Offset, VisLen & VisSep to the name, offs, size & next tags */
  290.  
  291.         char buf[10];   /* Well enough */
  292.  
  293.         UpdateTag(&vf->VisTags, NAME, vf->Name);
  294.         sprintf(buf, "%d", vf->Offset);
  295.         UpdateTag(&vf->VisTags, OFFS, buf);
  296.         sprintf(buf, "%d", vf->VisLen);
  297.         UpdateTag(&vf->VisTags, SIZE, buf);
  298.  
  299.         switch (vf->VisSep) {
  300.                 case ' ':
  301.                         UpdateTag(&vf->VisTags, NEXT, STR_SPACE); break;
  302.                 case '\t':
  303.                         UpdateTag(&vf->VisTags, NEXT, STR_TAB); break;
  304.                 case '\f':
  305.                         UpdateTag(&vf->VisTags, NEXT, STR_PARA); break;
  306.                 case '\n':
  307.                         UpdateTag(&vf->VisTags, NEXT, "nl"); break;
  308.         }
  309. }
  310.  
  311.  
  312. int ReadVisTags(struct Pro *Pr, struct VisFldInfo *vf)
  313. {
  314.         /* Parse vf's tags and fill vf. If information is incorrect, return RFF_ERR */
  315.         /* Information is incorrect when there is no corresponding field to an offset, */
  316.         /* or when there is a cycle gadget with no cycle entries. */
  317.  
  318.         struct RFFTag *nt;
  319.         struct FldInfo *f;
  320.         int i;
  321.  
  322.         if (nt = FindTag(&vf->VisTags, OFFS))
  323.                 vf->Offset = atoi(nt->Data);
  324.                 
  325.         if (nt = SearchTag(Pr, vf, NULL, SIZE)) vf->VisLen = atoi(nt->Data);
  326.         if (nt = SearchTag(Pr, vf, NULL, NEXT)) {
  327.                 if (!Stricmp(nt->Data,"space")) vf->VisSep = ' ';
  328.                 else if (!Stricmp(nt->Data,"tab")) vf->VisSep = '\t';
  329.                 else if (!Stricmp(nt->Data,"para")) vf->VisSep = '\f';
  330.         }
  331.  
  332.         /* Delete old cycle array if there was one */
  333.         if (vf->CEnt) {
  334.                 FreeMem(vf->CEnt, (vf->NEnt+1)*sizeof(char *));
  335.                 vf->CEnt = NULL;
  336.                 vf->NEnt = 0;
  337.         }
  338.  
  339.         if (nt = SearchTag(Pr, vf, NULL, FTYP)) {       /* Build new cycle array */
  340.                 if (!Stricmp(nt->Data,"cycle")) {
  341.                         if (nt = SearchTag(Pr, vf, NULL, CENT)) {
  342.                                 for (; nt; ++vf->NEnt, nt = NextSameTag(nt));
  343.                                 /* Now vf->NEnt holds the number of cycleentries */
  344.                                 if (nt = SearchTag(Pr, vf, NULL, CENT)) {
  345.                                         if (!(vf->CEnt =
  346.                                          AllocMem((vf->NEnt+1)*sizeof(char *), 0)))
  347.                                                 return MEM_ERR;
  348.                                         for (i=0; nt ;i++, nt = NextSameTag(nt))
  349.                                                 vf->CEnt[i] = nt->Data;
  350.                                         vf->CEnt[i] = NULL;     /* Nullterm cycleentrylist */
  351.                                 }
  352.                         }
  353.                         else return RFF_ERR;    /* There must be atleast one choice */
  354.                 }
  355.         }
  356.         f = GetFldInfo(Pr, vf->Offset);
  357.         if (nt = FindTag(&vf->VisTags, NAME))
  358.                 stccpy(vf->Name, nt->Data, FIELDNAMELENGTH);
  359.         else if (f) strcpy(vf->Name,f->Name);
  360.  
  361.         if (!f) return RFF_ERR; /* Finally check that there is a corresponding FldInfo */
  362.         return 0;
  363. }
  364.  
  365. /* End of support functions */
  366.  
  367.  
  368. struct RFFTag *FindTag(struct MinList *list, short int id)
  369. {
  370.         struct RFFTag *tag;
  371.         for (tag = (struct RFFTag *)list->mlh_Head; tag->mln.mln_Succ;
  372.          tag = (struct RFFTag *)tag->mln.mln_Succ) if (id == tag->ID) return tag;
  373.         return NULL;
  374. }
  375.  
  376. static struct RFFTag *FindTags(struct MinList *list, short tag1ID, short tag2ID)
  377. {
  378.         struct RFFTag *tag;
  379.         if (!(tag = FindTag(list, tag1ID)))
  380.                 if (tag2ID) tag = FindTag(list, tag2ID);
  381.         return tag;
  382. }
  383.  
  384. struct RFFTag *SearchTags(struct Pro *Pr, struct VisFldInfo *vf, Where *where, short tag1ID, short tag2ID)
  385. {
  386.         struct RFFTag *tag;
  387.         Where dummydest;
  388.         if (!where) where = &dummydest;
  389.  
  390.         /* Find the current VisualField */
  391.         if (!vf && !(vf = GetVisFldInfo(Pr->CurrentLayout, LastGad))) return NULL;
  392.  
  393.         if (tag = FindTags(&vf->VisTags, tag1ID, tag2ID)) *where = VIEW_LOCAL;
  394.         else if (tag = FindTags(&Pr->CurrentLayout->LayTags, tag1ID, tag2ID)) *where = VIEW_GLOBAL;
  395.         else if (tag = FindTags(&GetFldInfo(Pr, vf->Offset)->FldTags, tag1ID, tag2ID)) *where = PRO_LOCAL;
  396.         else if (tag = FindTags(&CurrentPro->ProTags, tag1ID, tag2ID)) *where = PRO_GLOBAL;
  397.  
  398.         return tag;
  399. }
  400.  
  401. struct RFFTag *SearchTag(struct Pro *Pr, struct VisFldInfo *vf, Where *where, short tagID)
  402. {
  403.         struct RFFTag *tag;
  404.         Where dummydest;
  405.         if (!where) where = &dummydest;
  406.  
  407.         /* Find the current VisualField */
  408.         if (!vf && !(vf = GetVisFldInfo(Pr->CurrentLayout, LastGad))) return NULL;
  409.  
  410.         if (tag = FindTag(&vf->VisTags, tagID)) *where = VIEW_LOCAL;
  411.         else if (tag = FindTag(&Pr->CurrentLayout->LayTags, tagID)) *where = VIEW_GLOBAL;
  412.         else if (tag = FindTag(&GetFldInfo(Pr, vf->Offset)->FldTags, tagID)) *where = PRO_LOCAL;
  413.         else if (tag = FindTag(&CurrentPro->ProTags, tagID)) *where = PRO_GLOBAL;
  414.  
  415.         return tag;
  416. }
  417.  
  418.  
  419. struct FldInfo *GetFldInfo(struct Pro *Pr, short Offset)
  420. {
  421.         /* Returns pointer to a FldInfo struct, returns NULL if not found */
  422.  
  423.         struct FldInfo *f, *old=NULL;
  424.         int i;
  425.         if (!Pr) return NULL; /* Safety, Should never happen */
  426.         for (f = Pr->FirstFldInfo, i=0; i<=Offset; f = f->Next, i++) {
  427.                 if (!f) return NULL;
  428.                 else old = f;
  429.         }
  430.         return old;
  431. }
  432.  
  433. struct VisFldInfo *GetVisFldInfo(struct Layout *Lay, struct Gadget *g)
  434. {
  435.         struct VisFldInfo *vf = Lay->FirstVisFldInfo;
  436.         for (;vf ;vf = vf->Next) if (vf->Gadget == g) break;
  437.         return vf;
  438. }
  439.  
  440. __inline char *SkipSpc(const char *s)
  441. {
  442.         /* Returns a pointer to the first non-space character or a pointer to NULL */
  443.         /* A comma is also considered a space */
  444.         /* if no non-space characters are found */
  445.         
  446.         while (*s && (*s == ' ' || *s == ',')) s++;
  447.         return s;
  448. }
  449.  
  450.  
  451. struct RFFTag *GetTag(const char **cursor)
  452. {
  453.         /* Takes a comma and tabseparated RFFLine and returns an RFFTag */
  454.         /* Starts searching from cursor which is also updated after each call */
  455.         /* Will return NULL when hitting a \t or \0 character */
  456.  
  457.         struct RFFTag *nt = NULL;
  458.         const char *brkchar, *nameptr, *dataptr = NULL;
  459.         int namelen, datalen;
  460.  
  461.         *cursor = SkipSpc(*cursor);
  462.  
  463.         if (**cursor == '\t') { 
  464.                 (*cursor)++;
  465.                 return NULL;
  466.         }
  467.         
  468.         /* Name part*/
  469.         if (brkchar = strpbrk(*cursor,"= ")) {
  470.                 namelen = brkchar - *cursor;
  471.                 nameptr = *cursor;
  472.                 *cursor = brkchar+1;
  473.  
  474.                 /* Data part */
  475.                 if (**cursor == '\"') { /* "Quotes" */
  476.                         if (brkchar = strpbrk(++(*cursor),"\"")) {      /* The other " */
  477.                                 datalen = brkchar - *cursor;
  478.                                 dataptr = *cursor;
  479.                                 *cursor = brkchar+1;
  480.                         }
  481.                 }
  482.                 else {  /* No quotes */
  483.                         if (brkchar = strpbrk(*cursor,", \t\n")) datalen = brkchar - *cursor;
  484.                         else datalen = strlen(*cursor);
  485.                         dataptr = *cursor;
  486.                         *cursor = brkchar;
  487.                 }
  488.                 if (dataptr) nt = NewTag(nameptr,namelen,dataptr,datalen);
  489.         }
  490.         return nt;
  491. }
  492.  
  493.  
  494. /*
  495. BOOL PutTag(struct RFFTag *tag, BPTR fp)
  496. {
  497.         if (FPuts(fp, tag->Name) == EOF) return FALSE;
  498.         if (FPutC(fp, '=') == EOF) return FALSE;
  499.         if (tag->Data && strlen(tag->Data)) {
  500.                 if (FPuts(fp, tag->Data) == EOF) return FALSE;
  501.         }
  502.         else if (FPuts(fp, "\"\"") == EOF) return FALSE;
  503.  
  504.         return TRUE;
  505. }
  506. */
  507.  
  508. BOOL PutTag(struct RFFTag *tag, BPTR fp)
  509. {
  510.         BOOL quotes = FALSE;
  511.         if (FPuts(fp, tag->Name) == EOF) return FALSE;
  512.         if (FPutC(fp, '=') == EOF) return FALSE;
  513.         if (tag->Data && strlen(tag->Data)) {
  514.                 if (strpbrk(tag->Data," ,\t")) {
  515.                         quotes = TRUE;
  516.                         if (FPutC(fp, '"') == EOF) return FALSE;
  517.                 }
  518.                 if (FPuts(fp, tag->Data) == EOF) return FALSE;
  519.                 if (quotes) if (FPutC(fp, '"') == EOF) return FALSE;
  520.         }
  521.         else if (FPuts(fp, "\"\"") == EOF) return FALSE;
  522.  
  523.         return TRUE;
  524. }
  525.  
  526.  
  527. BOOL PutTags(struct RFFTag *tag, BPTR fp)
  528. {
  529.         if (!PutTag(tag,fp)) return FALSE;
  530.         while (tag = NextTag(tag)) {
  531.                 if (FPutC(fp, ',') == EOF) return FALSE;
  532.                 if (!PutTag(tag,fp)) return FALSE;
  533.         }
  534.         return TRUE;
  535. }
  536.  
  537. BOOL RFFOut(struct Pro *Pr, BPTR fp)
  538. {
  539.         /* Writes all RFFtags to disk */
  540.  
  541.         struct Layout *lay;
  542.         struct FldInfo *f;
  543.         struct RxInfo *ri;
  544.         struct VisFldInfo *vf;
  545.         struct RFFLine *rl;
  546.         struct RFFTag *tag;
  547.  
  548.         /* Save schema:
  549.                 ProTags, all FldTags, \n 
  550.                 RxTags, \n
  551.                 for all layouts: LayTags, all VisTags \n
  552.                 (UnknownLines, \n)
  553.         */
  554.  
  555. ProTags:
  556.         if (!(tag = FirstTag(&Pr->ProTags))) goto RxTags;
  557.         if (!PutTags(tag,fp)) return FALSE;
  558.  
  559. FldTags:
  560.         for (f = Pr->FirstFldInfo; f; f = f->Next) {
  561.                 if (FPutC(fp, '\t') == EOF) return FALSE;
  562.                 if (!(tag = FirstTag(&f->FldTags))) continue;
  563.                 if (!PutTags(tag,fp)) return FALSE;
  564.         }
  565.         if (FPutC(fp, '\n') == EOF) return FALSE;
  566.  
  567. RxTags:
  568.         for (ri = Pr->FirstRxInfo; ri; ri = ri->Next) {
  569.                 if (ri != Pr->FirstRxInfo && FPutC(fp, '\t') == EOF) return FALSE;
  570.                 if (!(tag = FirstTag(&ri->RxTags))) continue;
  571.                 if (!PutTags(tag,fp)) return FALSE;
  572.         }
  573.         if (Pr->FirstRxInfo && FPutC(fp, '\n') == EOF) return FALSE;
  574.  
  575. Layouts:
  576.         for (lay = Pr->FirstLayout; lay; lay = lay->NextLayout) {
  577. Laytags:
  578.                 if (!(tag = FirstTag(&lay->LayTags))) continue;
  579.                 if (!PutTags(tag,fp)) return FALSE;
  580. VisTags:
  581.                 for (vf = lay->FirstVisFldInfo; vf; vf = vf->Next) {
  582.                         if (FPutC(fp, '\t') == EOF) return FALSE;
  583.                         if (!(tag = FirstTag(&vf->VisTags))) continue;
  584.                         if (!PutTags(tag,fp)) return FALSE;
  585.                 }
  586.                 if (FPutC(fp, '\n') == EOF) return FALSE;
  587.         }
  588.  
  589. UnknownLines:
  590.         for (rl = (struct RFFLine *)Pr->UnknownLines.mlh_Head; rl->mln.mln_Succ;
  591.          rl = (struct RFFLine *)rl->mln.mln_Succ) {
  592.                 if (FPuts(fp, rl->Line) == EOF) return FALSE;
  593.          }
  594.  
  595.         return TRUE;
  596. }
  597.  
  598.  
  599. BOOL DoASCIIParsing(struct Pro *Pr)
  600. {
  601.         /* Build default VisFldInfos if file lacks recognizable RFF lines */
  602.  
  603.         struct VisFldInfo *vf, *oldv = NULL;
  604.         struct FldInfo *f;
  605.         short off;
  606.  
  607.         if (!NewLayout(Pr)) return FALSE;
  608.  
  609.         /* Get the layoutname from the project name */
  610.         stccpy(Pr->CurrentLayout->Name, Pr->Name, LAYOUTNAMELENGTH);
  611.  
  612.         /* Add an @rff=1.1 and a type=form tag */
  613.         CreateAndAddTag(&Pr->CurrentLayout->LayTags, RFF, "1.1");
  614.         CreateAndAddTag(&Pr->CurrentLayout->LayTags, TYPE, "form");
  615.         
  616.         for (f = Pr->FirstFldInfo, off = 0; f; f = f->Next, off++) {
  617.                 if (!(vf = NewVisFldInfo())) return FALSE;
  618.                 strcpy(vf->Name,f->Name);                       /* Same name as the internal names */
  619.                 vf->Offset = off;
  620.                 WriteVisTags(vf);
  621.         
  622.                 /* Finally fix the links */
  623.                 if (!oldv) {
  624.                         oldv = vf;
  625.                         Pr->CurrentLayout->FirstVisFldInfo = vf;
  626.                 }
  627.                 else {  /* Fix backward links */
  628.                         oldv->Next = vf;
  629.                         oldv = vf;
  630.                 }
  631.         }
  632.         return TRUE;
  633. }
  634.  
  635. int DoParsing(BPTR fp, struct Pro *Pr, char *buffer)
  636. {
  637.         /* Do the actual parsing */
  638.         /* Return number of RFF lines found (both known and unknown */
  639.         /* Negative numbers indicate errors */
  640.  
  641.         char *cursor;
  642.         int n,len;
  643.         struct VisFldInfo *vf, *oldv;
  644.         struct FldInfo *f, *old = NULL;
  645.         struct RFFTag *nt;
  646.         struct RFFLine *rl;
  647.         short defoffset;
  648.         char *brkchar;
  649.         int ret;
  650.         
  651.         /* Read first line and build the FldInfo list */
  652.         if (!FGets(fp, buffer,BUFSIZE)) return FILE_ERR;
  653.         cursor = buffer;
  654.         while (brkchar = strpbrk(cursor,"\t\n")) {
  655.                 len = brkchar - cursor;
  656.                 if (len >= FIELDNAMELENGTH) return FILE_ERR;
  657.                 if (!(f = NewFldInfo())) return MEM_ERR;
  658.                 stccpy(f->Name, cursor,len+1);
  659.  
  660.                 if (!old) {
  661.                         old = f;
  662.                         Pr->FirstFldInfo = f;
  663.                 }
  664.                 else {  /* Fix previous links */
  665.                         old->Next = f;
  666.                         old = f;
  667.                 }
  668.                 cursor += len+1;
  669.         }
  670.         
  671.         /* Parse the RFF lines */
  672.  
  673.         for (n=0;;++n) {
  674.                 if (!FGets(fp, buffer,BUFSIZE)) return n;
  675.                 cursor=buffer;
  676.  
  677.                 /* In RFF1.x The first two tags has to be @RFF and TYPE */
  678.                 if (!(nt = GetTag(&cursor))) return n;  /* Not an RFF line */
  679.                 if (nt->ID != RFF) {                                                    /* Not an RFF line */
  680.                         DeleteTag(nt);
  681.                         return n;
  682.                 }
  683.                 if (Strnicmp(nt->Data,"1.",2)) {                                                /* Unknown RFF line */
  684.                         DeleteTag(nt);
  685.                         if (rl = NewRFFLine(buffer))
  686.                                 AddTail((struct List *)&Pr->UnknownLines, (struct Node *)rl);
  687.                         continue;
  688.                 }
  689.                 /* It's at least an RFF 1.1 line... */
  690.                 AddTail((struct List *)&Pr->ProTags, (struct Node *)nt);
  691.  
  692.                 if (!(nt = GetTag(&cursor))) return n;                  /* no more tags?? */
  693.                 if (nt->ID != TYPE) {                                                           /* Unknown RFF line */
  694.                         DeleteTag(nt);
  695.                         DeleteTag((struct RFFTag *)RemTail((struct List *)&Pr->ProTags));
  696.                         if (rl = NewRFFLine(buffer))
  697.                          AddTail((struct List *)&Pr->UnknownLines, (struct Node *)rl);
  698.                         continue;
  699.                 }
  700.                 
  701.                 /* Handle the different types */
  702.  
  703.                 if (!Stricmp(nt->Data,"internal")) {
  704.                         AddTail((struct List *)&Pr->ProTags, (struct Node *)nt);
  705.                 
  706.                         /* Add rest of tags till we hit the first \t char */
  707.                         while (nt = GetTag(&cursor))
  708.                                 AddTail((struct List *)&Pr->ProTags, (struct Node *)nt);
  709.  
  710.                         /* Work thru all tags adding information to the FldInfo structs */
  711.                         for (f = Pr->FirstFldInfo; f; f = f->Next) {
  712.                                 while (nt = GetTag(&cursor)) {
  713.                                         AddTail((struct List *)&f->FldTags, (struct Node *)nt);
  714.                                 }
  715.                                 if (nt = FindTag(&f->FldTags, FLEN)) f->Len = atoi(nt->Data);
  716.                         }
  717.  
  718.                         /* Change the portname of this project if the RXPORTNAME tag is found */
  719.                         if (nt = FindTag(&Pr->ProTags, RXPORTNAME)) {
  720.                                 if (MyRexxPort) CloseRexxPort(MyRexxPort);
  721.                                 if ((MyRexxPort = SetupRexxPort(nt->Data)) == NULL) return MEM_ERR;
  722.                         }
  723.                 }
  724.  
  725.                 else if (!Stricmp(nt->Data,"form")) {
  726.                         if (!NewLayout(Pr)) {
  727.                                 DeleteTag(nt);
  728.                                 return MEM_ERR;
  729.                         }
  730.                         AddHead((struct List *)&Pr->CurrentLayout->LayTags, RemTail((struct List *)&Pr->ProTags));
  731.                         AddTail((struct List *)&Pr->CurrentLayout->LayTags, (struct Node *)nt);
  732.  
  733.                         /* Add rest of tags till we hit the first \t char */
  734.                         while (nt = GetTag(&cursor))
  735.                                 AddTail((struct List *)&Pr->CurrentLayout->LayTags, (struct Node *)nt);
  736.  
  737.                         /* Get the layoutname from the taglist */
  738.                         if (nt = FindTag(&Pr->CurrentLayout->LayTags, LNAM))
  739.                                 stccpy(Pr->CurrentLayout->Name, nt->Data, LAYOUTNAMELENGTH);
  740.                         
  741.                         /* Read window position tags */
  742.                         {
  743.                                 struct RFFTag *xpos, *ypos;
  744.                                 if (xpos = FindTag(&Pr->CurrentLayout->LayTags, XPOS))
  745.                                         Pr->CurrentLayout->XPos = atoi(xpos->Data);
  746.                                 if (ypos = FindTag(&Pr->CurrentLayout->LayTags, YPOS))
  747.                                         Pr->CurrentLayout->YPos = atoi(ypos->Data);
  748.                         }
  749.                         /* Work thru all tags building VisFldInfo structs along the way */
  750.                         for (oldv=0, defoffset=0;;defoffset++) {
  751.                                 if (!(nt = GetTag(&cursor))) break;
  752.                                 if (!(vf = NewVisFldInfo())) {
  753.                                         DeleteTag(nt);
  754.                                         return MEM_ERR;
  755.                                 }
  756.                                 /* Fix the links now so we don't loose it if some error occurs */
  757.                                 if (!oldv) {
  758.                                         oldv = vf;
  759.                                         Pr->CurrentLayout->FirstVisFldInfo = vf;
  760.                                 }
  761.                                 else {  /* Fix backward links */
  762.                                         oldv->Next = vf;
  763.                                         oldv = vf;
  764.                                 }
  765.                                 
  766.                                 AddTail((struct List *)&vf->VisTags, (struct Node *)nt);
  767.                                 while (nt = GetTag(&cursor))
  768.                                         AddTail((struct List *)&vf->VisTags, (struct Node *)nt);
  769.  
  770.                                 /* Add values from the RFF tags */
  771.                                 vf->Offset = defoffset;
  772.                                 if ((ret = ReadVisTags(Pr, vf)) < 0) return ret;
  773.                                 defoffset = vf->Offset;
  774.                         }
  775.                 }
  776.                 else if (!Stricmp(nt->Data,"rxmenu")) {
  777.                         struct RxInfo *ri;
  778.                         if (!(Pr->FirstRxInfo = NewRxInfo())) return MEM_ERR;
  779.                         AddHead((struct List *)&Pr->FirstRxInfo->RxTags, RemTail((struct List *)&Pr->ProTags));
  780.                         AddTail((struct List *)&Pr->FirstRxInfo->RxTags, (struct Node *)nt);
  781.                         /* Add rest of tags till we hit the first \t char */
  782.                         while (nt = GetTag(&cursor))
  783.                                 AddTail((struct List *)&Pr->FirstRxInfo->RxTags, (struct Node *)nt);
  784.  
  785.                         /* Work thru all tags building RxInfo structs along the way */
  786.                         ri = Pr->FirstRxInfo;
  787.                         while ((nt = GetTag(&cursor)) && (ri = ri->Next = NewRxInfo())) {
  788.                                 AddTail((struct List *)&ri->RxTags, (struct Node *)nt);
  789.                                 while (nt = GetTag(&cursor))
  790.                                         AddTail((struct List *)&ri->RxTags, (struct Node *)nt);
  791.                         }
  792.                         if (nt) {
  793.                                 DeleteTag(nt);
  794.                                 return MEM_ERR;
  795.                         }
  796.                 }
  797.                 else {                                                          /* Other unknown RFF types */
  798.                         if (rl = NewRFFLine(buffer))
  799.                                 AddTail((struct List *)&Pr->UnknownLines, (struct Node *)rl);
  800.                         DeleteTag((struct RFFTag *)RemTail((struct List *)&Pr->ProTags));
  801.                         DeleteTag(nt);
  802.                         continue;
  803.                 }
  804.         }
  805. }
  806.  
  807.  
  808. BOOL IsBinary(BPTR fp)
  809. {
  810.         /* If the file contains at least one \0 character it's considered binary */
  811.         int d;
  812.         Rewind(fp);                                     // The last FGets() might have read past the file
  813.         while ((d = FGetC(fp)) != EOF)
  814.                 if (!d) return TRUE;
  815.         return FALSE;
  816. }
  817.  
  818.  
  819. int RFFParse(struct Pro *Pr, BPTR fp)
  820. {
  821.         /* Checks if fp is a valid RFF file. If so. The RFF tags will be parsed */
  822.         /* and inserted into the project. */
  823.         /* When finished, the next character read will be the first non-RFF line */
  824.  
  825.         char *buffer;
  826.         int n;  /* Retval from DoParsing(). Number of RFF lines in file */
  827.  
  828.         /* Allocate enough space for one line */
  829.         if (!(buffer = AllocMem(BUFSIZE,0))) return MEM_ERR;
  830.  
  831.         n = DoParsing(fp, Pr, buffer);
  832.         Pr->CurrentLayout = Pr->FirstLayout;    
  833.  
  834.         if (n > 0) {    /* Some RFF lines exist */
  835.                 Rewind(fp);
  836.                 while(1 + n--) FGets(fp, buffer, BUFSIZE);      /* first line and RFF lines */
  837.         }
  838.         else if (n == 0) {
  839.                 if (IsBinary(fp)) {
  840.                         FreeMem(buffer,BUFSIZE);
  841.                         return FILE_ERR;
  842.                 }
  843.                 else {                                                                                          /* An ASCII file */
  844.                         Rewind(fp);
  845.                         FGets(fp, buffer,BUFSIZE);                                      /* Skip 1st line */
  846.                 }
  847.         }
  848.         else {
  849.                 FreeMem(buffer,BUFSIZE);                                                /* Some error */
  850.                 return n;
  851.         }
  852.  
  853.         FreeMem(buffer,BUFSIZE);
  854.         if (!Pr->FirstLayout)           /* There has to be at least one layout */
  855.                 if (!DoASCIIParsing(Pr)) return MEM_ERR; /* Build default VisFldInfos */
  856.  
  857.         return 0;
  858. }
  859.