home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / education / a / biology1 / !Biology1 / c / FileRead < prev    next >
Text File  |  1991-12-03  |  11KB  |  381 lines

  1. /* c.fileread */
  2. /* To read the file of specified name into testdir */
  3. /* Returns error message if load failed */
  4.  
  5. #include <ctype.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #include "flex.h"
  10. #include "os.h"
  11. #include "werr.h"
  12.  
  13. #include "$.malcolm.txt2tst.TestTag.h"
  14. #include "data.h"
  15. #include "utils.h"
  16.  
  17. int  std_line;
  18.  
  19. static unsigned char *buffer;
  20. static unsigned char *ptr;
  21.  
  22. char *load_file (char *filename)
  23.   { os_filestr file_block;
  24.     int length;
  25.  
  26.     file_block.action = 17;     /* Read catalogue info */
  27.     file_block.name = filename;
  28.     if (os_file (&file_block))
  29.         return ("File not found");
  30.     if (file_block.action != 1)
  31.         return ("File not found");       /* Not a file */
  32.     length = file_block.start;
  33.  
  34.     if (0==flex_alloc ((flex_ptr)&buffer, length))
  35.         return ("Flex Failed");
  36.     
  37.     file_block.action = 255;
  38.     file_block.name = filename;
  39.     file_block.loadaddr = (int) buffer;
  40.     file_block.execaddr = 0;
  41.     if (os_file (&file_block))
  42.       { flex_free ((flex_ptr)&buffer);
  43.         return ("Problem loading data");       /* Some problem loading */
  44.       }
  45.     return (NULL);
  46.   }
  47.  
  48. void seek (long position)
  49.   { ptr = buffer + position;
  50.   }
  51.  
  52.  
  53. char rchar (void)
  54.   { return (*ptr++);
  55.   }
  56.  
  57. int rint (void)
  58.   { int res = *ptr++;
  59.     res = res + (*ptr << 8);
  60.     if (*ptr++ & 0x80)     /* as int is actually longer than 2 bytes */
  61.         res -= 0x10000;
  62.     return (res);
  63.   }
  64.  
  65. long rlong (void)
  66.   { long res = *ptr++;
  67.     res = res + ((long)*ptr++ << 8);
  68.     res = res + ((long)*ptr++ << 16);
  69.     res = res + ((long)*ptr++ << 24);
  70.     return (res);
  71.   }
  72.  
  73. char *rstring (void)
  74.   { int len = *ptr++;
  75.     char *str = malloc (len + 1);
  76.     if (str == NULL)
  77.         return (NULL);
  78.     memcpy (str, ptr, len);
  79.     str[len] = '\0';
  80.     ptr += len;
  81.     return (str);
  82.   }
  83.  
  84. void rtext (text *txt)
  85.   {
  86.  
  87. /* For now whilst text is saved as a string!!! */
  88.     char *str = rstring ();
  89.  
  90. /* Put in new lines up to line_len chars */
  91.  
  92.     char *line_start;
  93.  
  94.     for (line_start = str; *line_start; )
  95.       {
  96.         int max_eol = min (std_line, strlen (line_start)),
  97.             eol = max_eol;
  98.  
  99.         while (eol > 0 && line_start [eol] && line_start [eol] != ' ')
  100.             eol--;
  101.  
  102.         if (eol == 0)
  103.             eol = max_eol;
  104.  
  105.         line_start += eol;
  106.  
  107.         if (*line_start)
  108.           {
  109.             *line_start = '\n';
  110.             line_start ++;
  111.           } 
  112.       }
  113.     *txt = str;
  114.   }
  115.  
  116.  
  117. void reset_testdir (void)
  118.   { int i;
  119.     tdir.title = NULL;
  120.     tdir.appl_name = NULL;
  121.     for (i=0; i<26; i++)
  122.         tdir.udg[i].exists = FALSE;
  123.     tdir.no_topics = 0;
  124.     tdir.topic = NULL;
  125.   }
  126.  
  127. void reset_topic (topic *top)
  128.   { top->name = NULL;
  129.     top->shortname = NULL;
  130.     top->no_subtopics = 0;
  131.     top->subtopic = NULL;
  132.   }
  133.  
  134. void reset_subtopic (subtopic *sub)
  135.   { sub->menu_name    = NULL;
  136.     sub->title        = NULL;
  137.     sub->line_len     = 60;
  138.     std_line          = 60;
  139.     sub->header       = NULL;
  140.     sub->statement    = NULL;
  141.     sub->instruction1 = NULL;
  142.     sub->instruction2 = NULL;
  143.     sub->no_quest     = 0;
  144.     sub->question     = NULL;
  145.     sub->test_pic     = -1;
  146.     sub->test_asp     = -1;
  147.   }
  148.  
  149. void reset_question (question *q)
  150.   { q->quest      = NULL;
  151.     q->ans        = NULL;
  152.     q->iar        = NULL;
  153.     q->no_choice  = 0;
  154.     q->choice     = NULL;
  155.     q->quest_pic  = 0;
  156.     q->quest_asp  = 0;
  157.   }
  158.  
  159.  
  160. /* Extract information; it's ok to point into the flex block as
  161.  * I don't make any intervening flex calls, and I don't call wimp_poll
  162.  * so nobody else can either.
  163.  * Having established it's a correct file I make no consistancy checks
  164.  * here at all, it is intended that consistancy should be checked by
  165.  * txt2tst.
  166.  */
  167. char *decode_file (void)
  168.   { topic *top;
  169.     subtopic *sub;
  170.     question *quest;
  171.     char *str;
  172.     int num, tag;
  173.     int i,j;
  174.     int choice;
  175.  
  176.     seek (0L);
  177.     str = rstring ();
  178.     if (strcmp (str, "ReinfFile"))
  179.         return ("File format error");
  180.     free (str);
  181.     num = rint ();
  182.     if (num != Version)
  183.         return ("Unknown data version");
  184.     reset_testdir ();
  185.     do
  186.       { tag = rint ();
  187.         switch (tag)
  188.           { case END_TESTDIR :
  189.                 break;
  190.             case TITLE :
  191.                 tdir.title = rstring ();
  192.                 break;
  193.             case APPL_NAME :
  194.                 tdir.appl_name = rstring ();
  195.                 break;
  196.             case UDGS_TYPED :
  197.                 tdir.udgs_typed = rint ();
  198.                 break;
  199.             case NO_UDGS : /* I cater for 26 anyhow */
  200.                 rint ();
  201.                 break;
  202.             case UDG :
  203.                 num = rint ();
  204.                 tdir.udg[num].exists = TRUE;
  205.                 for (i=0; i<8; i++)
  206.                     tdir.udg[num].row[i] = rchar ();
  207.                 break;
  208.             case NO_TOPICS :
  209.                 tdir.no_topics = rint ();
  210.                 tdir.topic = malloc (tdir.no_topics * sizeof (topic));
  211.                 if (tdir.topic == NULL)
  212.                     return ("Malloc failed");
  213.                 top = NULL;
  214.                 break;
  215.             case TOPIC :
  216.                 if (top == NULL)
  217.                     top = tdir.topic;
  218.                 else
  219.                     top++;
  220.                 reset_topic (top);
  221.                 break;
  222.             case TOPIC_NAME :
  223.                 top->name = rstring ();
  224.                 break;
  225.             case TOPIC_SHORTNAME :
  226.                 top->shortname = rstring ();
  227.                 break;
  228.             case NO_SUBTOPICS :
  229.                 top->no_subtopics = rint ();
  230.                 top->subtopic = malloc (top->no_subtopics*sizeof(subtopic));
  231.                 if (top->subtopic == NULL)
  232.                     return ("Malloc failed");
  233.                 sub = NULL;
  234.                 break;
  235.             case SUBTOPIC :
  236.                 if (sub == NULL)
  237.                     sub = top->subtopic;
  238.                 else
  239.                     sub++;
  240.                 reset_subtopic (sub);
  241.                 break;
  242.             case SUBTOPIC_NAME :
  243.                 sub->menu_name = rstring ();
  244.                 break;
  245.             case LEAFNAME :  /* irelevant */
  246.                 free (rstring ());
  247.                 break;
  248.             case FILE_OFFSET :
  249.                 sub->offset = rlong ();
  250.                 break;
  251.             default :
  252.                 return ("Unknown testdir tag");
  253.           }
  254.       } while (tag != END_TESTDIR);
  255.     for (top = tdir.topic, i=0; i<tdir.no_topics; top++, i++)
  256.       { for (sub = top->subtopic, j=0; j<top->no_subtopics; sub++, j++)
  257.           { seek (sub->offset);
  258.             std_line = 60;
  259.             do
  260.               { tag = rint ();
  261.                 switch (tag)
  262.                   { case END_TEST :
  263.                         break;
  264.                     case TEST_TITLE :
  265.                         sub->title = rstring ();
  266.                         break;
  267.                     case HEADER :
  268.                         rtext (&sub->header);  
  269.                         break;
  270.                     case STATEMENT :
  271.                         rtext (&sub->statement);
  272.                         break;
  273.                     case INSTRUCTION1 :
  274.                         rtext (&sub->instruction1);
  275.                         break;
  276.                     case INSTRUCTION2 :
  277.                         rtext (&sub->instruction2);
  278.                         break;
  279.                     case TEST_TYPE :
  280.                         sub->test_type = rint ();
  281.                         break;
  282.                     case RESPONSE_TYPE :
  283.                         sub->res_type = rint ();
  284.                         break;
  285.                     case TEST_PIC :
  286.                         sub->test_pic = rint ();
  287.                         break;
  288.                     case TEST_ASP :
  289.                         sub->test_asp = rint ();
  290.                         break;
  291.                     case NO_QUESTIONS :
  292.                         sub->no_quest = rint ();
  293.                         sub->question =
  294.                              malloc (sub->no_quest * sizeof (question));
  295.                         if (sub->question == NULL)
  296.                             return ("Malloc failed");
  297.                         quest = NULL;
  298.                         break;
  299.                     case QUESTION :
  300.                         if (quest == NULL)
  301.                             quest = sub->question;
  302.                         else
  303.                             quest++;
  304.                         reset_question (quest);
  305.                         break;
  306.                     case QUEST_TEXT :
  307.                         rtext (&quest->quest);
  308.                         break;
  309.                     case ANSWER_TEXT :
  310.                         rtext (&quest->ans);
  311.                         break;
  312.                     case IAR_TEXT :
  313.                         rtext (&quest->iar);
  314.                         break;
  315.                     case NO_CHOICE :
  316. /* this covers hints and clues - they are stored as choices by txt2tst */
  317.                         quest->no_choice = rint ();
  318.                         quest->choice = malloc (quest->no_choice
  319.                                                 * sizeof (text));
  320.                         if (quest->choice == NULL)
  321.                             return ("Malloc failed");
  322.                         choice = 0;
  323.                         break;
  324.                     case CHOICE :
  325.                         rtext (&quest->choice[choice++]);
  326.                         break;
  327. /*                    case NO_HINTS :
  328.                         quest->no_hints = rint ();
  329.                         quest->hint = malloc (quest->no_hints
  330.                                                 * sizeof (text));
  331.                         if (quest->hint == NULL)
  332.                             return ("Malloc failed");
  333.                         hint = 0;
  334.                         break;
  335.                     case HINT :
  336.                         rtext (&quest->hint[hint++]);
  337.                         break;
  338.                     case NO_CLUES :
  339.                         quest->no_clues = rint ();
  340.                         quest->clue = malloc (quest->no_clues
  341.                                                 * sizeof (text));
  342.                         if (quest->clue == NULL)
  343.                             return ("Malloc failed");
  344.                         clue = 0;
  345.                         break;
  346.                     case CLUE :
  347.                         rtext (&quest->clue[clue++]);
  348.                         break;                               */
  349.                     case QUEST_PIC :
  350.                         quest->quest_pic = rint ();
  351.                         break;
  352.                     case QUEST_ASP :
  353.                         quest->quest_asp = rint ();
  354.                         break;
  355.                     case LINE_LEN :
  356.                         sub->line_len = rint ();
  357.                         std_line = sub->line_len;
  358.                         break;
  359.                     default :
  360.                         return ("Unknown test tag");
  361.                   } /* switch */
  362.               } while (tag != END_TEST);
  363.           } /* for sub loop */
  364.       }  /* for top loop */
  365.     return (NULL);
  366.   }
  367.  
  368.  
  369. char *read_testdir (char *filename)
  370.  {  char *err = NULL;
  371.  
  372.     if ((err = load_file (filename)) != NULL)
  373.         return (err);
  374.  
  375.     err = decode_file ();
  376.  
  377.     flex_free ((flex_ptr)&buffer);
  378.  
  379.     return (err);
  380.   }
  381.